diff --git a/app/.gitignore b/app/.gitignore index b2614db..7daa59f 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1,28 +1,28 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* - - -# remove zip -*.zip -**/temp/ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* + + +# remove zip +*.zip +**/temp/ diff --git a/app/.husky/_/pre-commit b/app/.husky/_/pre-commit index d461e99..2bb0ba2 100644 --- a/app/.husky/_/pre-commit +++ b/app/.husky/_/pre-commit @@ -1,25 +1,25 @@ -#!/usr/bin/env bash - -echo "Running pre-commit hook..." - -# Compile TypeScript -echo "Compiling TypeScript..." -npx tsc scripts/validate-filenames.ts - -# if [ $? -ne 0 ]; then -# echo "TypeScript compilation failed. Aborting commit." -# exit 1 -# fi - -echo "TypeScript compilation successful." - -# Run Node.js script -echo "Running Node.js script..." -node scripts/validate-filenames.js --no-prompt - -if [ $? -ne 0 ]; then - echo "Node.js script failed. Aborting commit." - exit 1 -fi - -echo "Pre-commit hook completed successfully." +#!/usr/bin/env bash + +echo "Running pre-commit hook..." + +# Compile TypeScript +echo "Compiling TypeScript..." +npx tsc scripts/validate-filenames.ts + +# if [ $? -ne 0 ]; then +# echo "TypeScript compilation failed. Aborting commit." +# exit 1 +# fi + +echo "TypeScript compilation successful." + +# Run Node.js script +echo "Running Node.js script..." +node scripts/validate-filenames.js --no-prompt + +if [ $? -ne 0 ]; then + echo "Node.js script failed. Aborting commit." + exit 1 +fi + +echo "Pre-commit hook completed successfully." diff --git a/app/.husky/pre-commit b/app/.husky/pre-commit index d461e99..2bb0ba2 100644 --- a/app/.husky/pre-commit +++ b/app/.husky/pre-commit @@ -1,25 +1,25 @@ -#!/usr/bin/env bash - -echo "Running pre-commit hook..." - -# Compile TypeScript -echo "Compiling TypeScript..." -npx tsc scripts/validate-filenames.ts - -# if [ $? -ne 0 ]; then -# echo "TypeScript compilation failed. Aborting commit." -# exit 1 -# fi - -echo "TypeScript compilation successful." - -# Run Node.js script -echo "Running Node.js script..." -node scripts/validate-filenames.js --no-prompt - -if [ $? -ne 0 ]; then - echo "Node.js script failed. Aborting commit." - exit 1 -fi - -echo "Pre-commit hook completed successfully." +#!/usr/bin/env bash + +echo "Running pre-commit hook..." + +# Compile TypeScript +echo "Compiling TypeScript..." +npx tsc scripts/validate-filenames.ts + +# if [ $? -ne 0 ]; then +# echo "TypeScript compilation failed. Aborting commit." +# exit 1 +# fi + +echo "TypeScript compilation successful." + +# Run Node.js script +echo "Running Node.js script..." +node scripts/validate-filenames.js --no-prompt + +if [ $? -ne 0 ]; then + echo "Node.js script failed. Aborting commit." + exit 1 +fi + +echo "Pre-commit hook completed successfully." diff --git a/app/Dockerfile b/app/Dockerfile index b85937d..0c5c8ac 100644 --- a/app/Dockerfile +++ b/app/Dockerfile @@ -1,51 +1,51 @@ -# Use the argument for node version (defaults to 'lts' if not provided) -ARG NODE_VERSION=lts - -# Stage 1: Build React App -FROM node:${NODE_VERSION}-alpine AS development - -# Set the Node.js environment to development -ENV NODE_ENV=development - -# Define build arguments for the API base URLs -ARG REACT_APP_SERVER_SOCKET_API_BASE_URL -ARG REACT_APP_SERVER_REST_API_BASE_URL -ARG REACT_APP_SERVER_MARKETPLACE_URL - -# Set environment variables for the API base URLs using the build arguments -ENV REACT_APP_SERVER_SOCKET_API_BASE_URL=${REACT_APP_SERVER_SOCKET_API_BASE_URL} -ENV REACT_APP_SERVER_REST_API_BASE_URL=${REACT_APP_SERVER_REST_API_BASE_URL} -ENV REACT_APP_SERVER_MARKETPLACE_URL=${REACT_APP_SERVER_MARKETPLACE_URL} - -# Set working directory for frontend code -WORKDIR /frontend - -# Copy package.json and package-lock.json for npm install -COPY package*.json ./ - -# Install the latest npm version -RUN npm install -g npm - -# Install dependencies (this includes react-scripts) -RUN npm install --legacy-peer-deps - -# Copy the rest of the application code -COPY . . - -# Run the build command (build the React app) -RUN npm run build - -# Stage 2: Serve with Nginx -FROM nginx:alpine - -# Copy the built React files from the build stage into Nginx's default HTML folder -COPY --from=development /frontend/build /usr/share/nginx/html - -# Optionally copy a custom Nginx config (if needed) -COPY nginx.conf /etc/nginx/conf.d/default.conf - -# Expose port 80 for Nginx (default HTTP port) -EXPOSE 80 - -# Start Nginx in the foreground (this is required to keep the container running) -CMD ["nginx", "-g", "daemon off;"] +# Use the argument for node version (defaults to 'lts' if not provided) +ARG NODE_VERSION=lts + +# Stage 1: Build React App +FROM node:${NODE_VERSION}-alpine AS development + +# Set the Node.js environment to development +ENV NODE_ENV=development + +# Define build arguments for the API base URLs +ARG REACT_APP_SERVER_SOCKET_API_BASE_URL +ARG REACT_APP_SERVER_REST_API_BASE_URL +ARG REACT_APP_SERVER_MARKETPLACE_URL + +# Set environment variables for the API base URLs using the build arguments +ENV REACT_APP_SERVER_SOCKET_API_BASE_URL=${REACT_APP_SERVER_SOCKET_API_BASE_URL} +ENV REACT_APP_SERVER_REST_API_BASE_URL=${REACT_APP_SERVER_REST_API_BASE_URL} +ENV REACT_APP_SERVER_MARKETPLACE_URL=${REACT_APP_SERVER_MARKETPLACE_URL} + +# Set working directory for frontend code +WORKDIR /frontend + +# Copy package.json and package-lock.json for npm install +COPY package*.json ./ + +# Install the latest npm version +RUN npm install -g npm + +# Install dependencies (this includes react-scripts) +RUN npm install --legacy-peer-deps + +# Copy the rest of the application code +COPY . . + +# Run the build command (build the React app) +RUN npm run build + +# Stage 2: Serve with Nginx +FROM nginx:alpine + +# Copy the built React files from the build stage into Nginx's default HTML folder +COPY --from=development /frontend/build /usr/share/nginx/html + +# Optionally copy a custom Nginx config (if needed) +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# Expose port 80 for Nginx (default HTTP port) +EXPOSE 80 + +# Start Nginx in the foreground (this is required to keep the container running) +CMD ["nginx", "-g", "daemon off;"] diff --git a/app/README.md b/app/README.md index 9db40e3..bb10322 100644 --- a/app/README.md +++ b/app/README.md @@ -1,99 +1,99 @@ -## Getting Started - -Follow these steps to set up and run the project locally. - -### Prerequisites - -Ensure you have the following installed on your system: - -- **Node.js**: [Download and install Node.js](https://nodejs.org/) -- **npm**: Comes with Node.js, but you can also install [npm separately](https://www.npmjs.com/get-npm) -- **yarn (optional)**: If you prefer to use Yarn, [install it here](https://yarnpkg.com/) -- **TypeScript**: This project uses TypeScript, and the necessary dependencies will be installed automatically. - -### Installation - -1. Clone the repository: - - ```bash - git clone https://github.com/S0Vishnu/react-production-project-boilerplate.git - cd react-production-project-boilerplate - ``` - -2. Cloning repository with User Credentials: - - ```bash - git clone https://your_username:password@github.com/S0Vishnu/react-production-project-boilerplate.git - cd react-production-project-boilerplate - ``` - - note: if password contains special charecters use: - - - @ → %40 - - : → %3A - - / → %2F - - ? → %3F - - & → %26 - - = → %3D - - ! → %21 - -2. Install the dependencies: - - ```bash - npm install - ``` - -3. Start server: - - ```bash - npm start - ``` - -4. Build the app for production: - - ```bash - npm run build - ``` - -5. Tests - - This project includes both **unit tests** using **Jest** and **end-to-end (E2E) tests** using **Cypress**. Here’s how you can run and manage these tests. - - **Unit Tests (Jest)** - Unit tests are located in the `src/tests/unit/` directory. They test individual components and functions to ensure they work as expected. **Jest** is used for running these tests. - - **Running Unit Tests** - To run the unit tests, use the following command: - - ```bash - npm run test - ``` - - **End-to-End (E2E) Tests (Cypress)** - Cypress can be run in two modes - - 1. Interactive Mode: - - ```bash - npm run cypress:open - ``` - - 2. Headless Mode: - - ```bash - npm run cypress:run - ``` - -### Run Documentation(Docsify) - -1. Installation (if needed): - - ```bash - npm i docsify-cli -g - ``` - -2. Run Command: - - ```bash - docsify serve docs - ``` +## Getting Started + +Follow these steps to set up and run the project locally. + +### Prerequisites + +Ensure you have the following installed on your system: + +- **Node.js**: [Download and install Node.js](https://nodejs.org/) +- **npm**: Comes with Node.js, but you can also install [npm separately](https://www.npmjs.com/get-npm) +- **yarn (optional)**: If you prefer to use Yarn, [install it here](https://yarnpkg.com/) +- **TypeScript**: This project uses TypeScript, and the necessary dependencies will be installed automatically. + +### Installation + +1. Clone the repository: + + ```bash + git clone https://github.com/S0Vishnu/react-production-project-boilerplate.git + cd react-production-project-boilerplate + ``` + +2. Cloning repository with User Credentials: + + ```bash + git clone https://your_username:password@github.com/S0Vishnu/react-production-project-boilerplate.git + cd react-production-project-boilerplate + ``` + + note: if password contains special charecters use: + + - @ → %40 + - : → %3A + - / → %2F + - ? → %3F + - & → %26 + - = → %3D + - ! → %21 + +2. Install the dependencies: + + ```bash + npm install + ``` + +3. Start server: + + ```bash + npm start + ``` + +4. Build the app for production: + + ```bash + npm run build + ``` + +5. Tests + + This project includes both **unit tests** using **Jest** and **end-to-end (E2E) tests** using **Cypress**. Here’s how you can run and manage these tests. + + **Unit Tests (Jest)** + Unit tests are located in the `src/tests/unit/` directory. They test individual components and functions to ensure they work as expected. **Jest** is used for running these tests. + + **Running Unit Tests** + To run the unit tests, use the following command: + + ```bash + npm run test + ``` + + **End-to-End (E2E) Tests (Cypress)** + Cypress can be run in two modes + + 1. Interactive Mode: + + ```bash + npm run cypress:open + ``` + + 2. Headless Mode: + + ```bash + npm run cypress:run + ``` + +### Run Documentation(Docsify) + +1. Installation (if needed): + + ```bash + npm i docsify-cli -g + ``` + +2. Run Command: + + ```bash + docsify serve docs + ``` diff --git a/app/docs/README.md b/app/docs/README.md index 51b6e46..252c1b9 100644 --- a/app/docs/README.md +++ b/app/docs/README.md @@ -1,18 +1,18 @@ -# Boilerplate Project - -A **Boilerplate Project** designed to jumpstart your development process with a clean, organized, and scalable structure. - -## Features - -- **Pre-configured Tooling**: Includes [Tool1], [Tool2], and [Tool3] for seamless development. -- **Modular Structure**: Organized folder structure for scalability and maintainability. -- **Best Practices**: Follows industry standards for coding, linting, and testing. -- **Cross-Environment Compatibility**: Ready for local, staging, and production environments. - -## Technologies Used - -- **Frontend**: React -- **Backend**: Node.js -- **Database**: [MongoDB, PostgreSQL, MySQL, etc.] -- **Build Tools**: Webpack -- **Testing**: Jest +# Boilerplate Project + +A **Boilerplate Project** designed to jumpstart your development process with a clean, organized, and scalable structure. + +## Features + +- **Pre-configured Tooling**: Includes [Tool1], [Tool2], and [Tool3] for seamless development. +- **Modular Structure**: Organized folder structure for scalability and maintainability. +- **Best Practices**: Follows industry standards for coding, linting, and testing. +- **Cross-Environment Compatibility**: Ready for local, staging, and production environments. + +## Technologies Used + +- **Frontend**: React +- **Backend**: Node.js +- **Database**: [MongoDB, PostgreSQL, MySQL, etc.] +- **Build Tools**: Webpack +- **Testing**: Jest diff --git a/app/docs/_sidebar.md b/app/docs/_sidebar.md index cc67d9f..f2e3c8c 100644 --- a/app/docs/_sidebar.md +++ b/app/docs/_sidebar.md @@ -1,12 +1,12 @@ -- [Get Started](/README.md) - - - - - -- [Git Commands](./documents/gitNotes.md) -- [Notes and Guidlines](./documents/notes.md) -- [Project Structure](./documents/projectStructure.md) -- [How to Document](./documents/documentationGuide.md) -- [How to Write a Markdown (.md)](./documents/markdownGuide.md) -- [Docsify Overview](./documents/docsifyGuide.md) +- [Get Started](/README.md) + + + + + +- [Git Commands](./documents/gitNotes.md) +- [Notes and Guidlines](./documents/notes.md) +- [Project Structure](./documents/projectStructure.md) +- [How to Document](./documents/documentationGuide.md) +- [How to Write a Markdown (.md)](./documents/markdownGuide.md) +- [Docsify Overview](./documents/docsifyGuide.md) diff --git a/app/docs/assets/images/gitWorkFlow.svg b/app/docs/assets/images/gitWorkFlow.svg index f1a3f8c..e75663c 100644 --- a/app/docs/assets/images/gitWorkFlow.svg +++ b/app/docs/assets/images/gitWorkFlow.svg @@ -1,10 +1,10 @@ - - - - - - - + + + + + + + WorkspaceStaging areaLocal repositoryRemote repositorygit add .git commit -m "message"git pushgit fetchgit pull \ No newline at end of file diff --git a/app/docs/documents/docsifyGuide.md b/app/docs/documents/docsifyGuide.md index c4a90f6..a586055 100644 --- a/app/docs/documents/docsifyGuide.md +++ b/app/docs/documents/docsifyGuide.md @@ -1,35 +1,35 @@ -# Quick start - -It is recommended to install `docsify-cli` globally, which helps initializing and previewing the website locally. - -```bash -npm i docsify-cli -g -``` - -### Initialize - -If you want to write the documentation in the `./docs` subdirectory, you can use the `init` command. - -```bash -docsify init ./docs -``` - -### Writing content - -After the `init` is complete, you can see the file list in the `./docs` subdirectory. - -- `index.html` as the entry file -- `README.md` as the home page -- `.nojekyll` prevents GitHub Pages from ignoring files that begin with an underscore - -You can easily update the documentation in `./docs/README.md`, of course you can add more pages. - -### Preview your site - -Run the local server with `docsify serve`. You can preview your site in your browser on `http://localhost:3000`. - -```bash -docsify serve docs -``` - +# Quick start + +It is recommended to install `docsify-cli` globally, which helps initializing and previewing the website locally. + +```bash +npm i docsify-cli -g +``` + +### Initialize + +If you want to write the documentation in the `./docs` subdirectory, you can use the `init` command. + +```bash +docsify init ./docs +``` + +### Writing content + +After the `init` is complete, you can see the file list in the `./docs` subdirectory. + +- `index.html` as the entry file +- `README.md` as the home page +- `.nojekyll` prevents GitHub Pages from ignoring files that begin with an underscore + +You can easily update the documentation in `./docs/README.md`, of course you can add more pages. + +### Preview your site + +Run the local server with `docsify serve`. You can preview your site in your browser on `http://localhost:3000`. + +```bash +docsify serve docs +``` + ?> For more use cases of `docsify-cli`, head over to the [docsify-cli documentation](https://github.com/docsifyjs/docsify-cli). \ No newline at end of file diff --git a/app/docs/documents/documentationGuide.md b/app/docs/documents/documentationGuide.md index b189a25..db3e8db 100644 --- a/app/docs/documents/documentationGuide.md +++ b/app/docs/documents/documentationGuide.md @@ -1,380 +1,380 @@ -# Why Documentation is Important for Developers - -Documentation helps developers work efficiently and ensures projects run smoothly. Here’s why it’s crucial: - -1. **Knowledge Sharing**: It helps team members understand the system and communicate effectively, especially when new people join the project. - -2. **Code Maintenance**: Good documentation makes it easier to fix bugs, make updates, and keep the code consistent. - -3. **Project Longevity**: It ensures that project knowledge is preserved, so future developers can maintain or improve the code without confusion. - -4. **Troubleshooting**: Developers can quickly find solutions to problems or understand past decisions, saving time and reducing errors. - -5. **Testing and Quality**: Documentation helps ensure the right testing processes are followed, leading to better-quality code. - -6. **Efficiency**: It saves time by reducing the need to explain things repeatedly or search for answers. - -In short, internal documentation keeps projects organized, helps teams collaborate, and ensures the software can be maintained and improved over time. - ---- - -## Guide to Writing Modular Documentation for React Projects - -Modular documentation refers to organizing your documentation into independent, reusable sections or modules. Each module typically covers a specific part of your project, making it easier to update and navigate. - -In the context of React, modular documentation should cover both React components and the overall architecture of the app. - -### Split Documentation into Smaller Sections - -When documenting, break down each part of your codebase into its smallest logical unit: - -1. **Functions**: Explain its purpose, inputs (arguments), and outputs (returns). -2. **Components**: Detail props, their types, default values, and the UI they render. -3. **Utilities/Helpers**: Document what a utility does, its inputs, and outputs. -4. **APIs**: Cover the endpoint, request format, and expected response. - -Each section should have a consistent structure for easy understanding and reference. - -## Documenting Functions - -#### Structure for Documenting Functions - -1. **Function Name**: A short and descriptive name. -2. **Purpose**: Briefly explain what the function does. -3. **Inputs**: - - List each parameter. - - Include types and default values if applicable. -4. **Output**: Describe the return value and its type. -5. **Code Examples**: Provide a usage example. - -#### Example: Utility Function Documentation - -````markdown -## `formatDate` - -### Purpose - -The `formatDate` function converts a `Date` object into a human-readable string format. - -### Inputs - -| Parameter | Type | Default Value | Description | -| --------- | -------- | ------------- | -------------------------- | -| `date` | `Date` | - | The date object to format. | -| `locale` | `string` | `"en-US"` | The locale for formatting. | - -### Output - -Returns a `string` representing the formatted date. - -### Example - -```javascript -import { formatDate } from "./utils"; - -const date = new Date("2024-11-21"); -console.log(formatDate(date)); // Output: "November 21, 2024" -``` -```` - -## Documenting Components - -#### Structure for Documenting Components - -1. **Component Name**: Name of the React component. -2. **Purpose**: Explain what the component is for and its use case. -3. **Props**: - - List each prop. - - Include type, whether it’s required, and default value. -4. **Behavior**: Describe what the component does and any side effects. -5. **Output**: Explain what the component renders or returns. -6. **Code Examples**: Show how to use the component. - -#### Example: Component Documentation - -`````markdown -## `Button` - -### Purpose - -The `Button` component renders a clickable button with customizable styles and behavior. - -### Props - -| Prop Name | Type | Required | Default Value | Description | -| ---------- | ---------- | -------- | ------------- | ---------------------------------- | -| `label` | `string` | Yes | - | The text displayed on the button. | -| `onClick` | `function` | No | `() => {}` | The function to call when clicked. | -| `disabled` | `boolean` | No | `false` | Disables the button if true. | -| `style` | `object` | No | `{}` | Inline styles for the button. | - -### Behavior - -- If `disabled` is true, the button cannot be clicked. -- The `onClick` function will only be called when the button is enabled. - -### Output - -Renders a `
` wrapper. -- An `` field styled with default or custom styles. - -### Example - -```jsx -import SearchBar from "./components/SearchBar"; - - console.log(query)} - debounce={500} -/>; -``` -```` -````` - -## Documenting Custom Hooks - -#### Structure for Documenting Hooks - -1. **Hook Name**: Name of the hook. -2. **Purpose**: Why it’s used and what it does. -3. **Inputs**: Parameters passed to the hook. -4. **State/Outputs**: State or values returned by the hook. -5. **Usage**: Show an example. - -#### Example: Hook Documentation - -````markdown -## `useFetch` - -### Purpose - -The `useFetch` hook manages data fetching and provides loading, error, and response states. - -### Inputs - -| Parameter | Type | Required | Default Value | Description | -| --------- | -------- | -------- | ------------- | ------------------------------------- | -| `url` | `string` | Yes | - | The endpoint to fetch data from. | -| `options` | `object` | No | `{}` | Fetch options like headers or method. | - -### State/Outputs - -| State Name | Type | Description | -| ---------- | --------- | ---------------------------------------- | -| `data` | `any` | The response data from the API. | -| `loading` | `boolean` | Indicates if the request is in progress. | -| `error` | `object` | The error object if the request fails. | - -### Example - -```javascript -import { useFetch } from "./hooks/useFetch"; - -const MyComponent = () => { - const { data, loading, error } = useFetch("/api/data"); - - if (loading) return

Loading...

; - if (error) return

Error: {error.message}

; - - return
{JSON.stringify(data)}
; -}; -``` -```` - -#### General Best Practices for Modular Documentation - -1. **Be Consistent**: Use the same format for all functions, components, and hooks. -2. **Focus on Inputs and Outputs**: Developers care about what they give and what they get. -3. **Use Examples**: Code examples make documentation actionable. -4. **Avoid Overloading**: Document each function/component in its own file if it’s complex. -5. **Explain Behavior**: Describe any side effects, state changes, or interactions. - ---- - -## Guide to Managing Files and Folders for Documentation in Docsify - -Docsify is a flexible tool for generating documentation from markdown files. To keep your Docsify-based project well-organized, here’s a guide on how to manage files and folders effectively. - -#### 1. Project Structure Overview - -A clean folder structure is crucial for scalability, readability, and ease of maintenance. Below is a suggested structure: - -``` -/docs # Root folder for your Docsify project -│ -├── /assets/ # Static resources (images, videos, files, etc.) -│ └── /images/ # Folder for images used in your docs -│ └── gitWorkFlow.svg # Example image used in documentation -│ └── /videos/ # Folder for tutorial videos or related media -│ └── walkthrough.mp4 # old walkthrough presentation -│ -├── /documents/ # Folder for the main documentation content -│ └── docsifyGuide.md # Documentation for setting up and using Docsify -│ └── projectStructure.md # Explanation of the project structure and organization -│ └── /components/ # Folder for documentation on different components -│ └── input.md # Input component documentation -│ └── others.md # Other components documentation -│ └── etc.md # Any additional miscellaneous documentation -│ -├── /style/ # Folder for custom styles -│ └── style.css # Custom CSS file for styling the documentation -│ -└── index.html # Main entry point for Docsify (loads the documentation) - -``` - ---- - -#### 2. Folder Breakdown - -- **/docs**: This is the core folder that contains all of your Markdown (`.md`) files. You can organize these files by sections or topics such as guides, API references, and tutorials. Subfolders like `/guide`, `/reference`, or `/tutorials` help keep related files together. - -- **/assets**: This folder is for any images, diagrams, videos, or other static files referenced in your documentation. It's best to organize your media into subfolders based on the section they belong to. - - Example: - - ``` - /assets - ├── /images/ - │ ├── diagram1.png - │ └── screenshot.png - └── /videos/ - └── tutorial.mp4 - ``` - -- **/lib**: If you want to add custom JavaScript or other scripts to enhance Docsify’s functionality, place them in the `/lib` folder. This can include themes, custom navigation, or interactive features. - ---- - -#### 3. Naming Conventions - -Use simple, descriptive names for your files and folders. Avoid spaces in filenames—use hyphens (`-`) instead. For example: - -- **Correct**: `installation-guide.md`, `api-reference.md` -- **Incorrect**: `installation guide.md`, `api reference.md` - -This keeps URLs and links consistent and easier to handle. - ---- - -#### 4. Organizing Documentation Files - -1. **Homepage (index.md)**: - The `index.md` file serves as the homepage for your documentation. It should provide an introduction to the project and link to other sections of your documentation. - -2. **Guide Section**: - Place introductory content, installation instructions, and tutorials in the `/guide` folder. Each file should be named based on its content (e.g., `installation.md`, `getting-started.md`). - -3. **Reference Section**: - For API documentation or technical references, create a `/reference` folder. You might have files like `api-reference.md`, `config.md`, or `troubleshooting.md`. - -4. **Assets**: - Organize images, videos, or diagrams in the `/assets` folder. Keep this structure consistent across sections (e.g., `/assets/images/`, `/assets/videos/`). - ---- - -#### 5. Writing the \_sidebar.md File - -The `_sidebar.md` file controls the sidebar navigation in Docsify. It defines the links that appear on the sidebar, which can point to sections of the documentation or external URLs. - -Here’s how to structure the `_sidebar.md` file: - -- **Basic Structure**: - You can list the sections of your documentation as clickable links. Use Markdown syntax to link to the different `.md` files within your `/docs` folder. - - Example: - - ```markdown - - [Home](/) # Link to the homepage - - [Getting Started](/guide/intro.md) # Link to the "Getting Started" guide - - [API Reference](/reference/api.md) # Link to the API documentation - - [Installation](/guide/installation.md) # Link to the installation guide - ``` - -- **Nested Links**: - To organize sections into subcategories, you can nest links under headings. This helps create a hierarchical structure in the sidebar. - - Example: - - ```markdown - - [Home](/) - - [Guide](/guide/intro.md) - - [Introduction](/guide/intro.md) - - [Usage](/guide/usage.md) - - [API Reference](/reference/api.md) - - [Authentication](/reference/authentication.md) - - [Endpoints](/reference/endpoints.md) - ``` - -- **External Links**: - You can also add external links to resources outside of your Docsify project. - - Example: - - ```markdown - - [External Resource](https://example.com) - ``` - ---- - -#### 6. Managing Large Projects - -For large documentation projects, it’s best to break content into smaller, manageable sections. This will help keep the documentation organized and make it easier for team members to collaborate. - -- **Modular Sections**: - Use subfolders like `/getting-started/`, `/setup/`, and `/troubleshooting/` to logically divide your content. Each section should have its own introduction, details, and examples. - -- **Indexing**: - Consider creating an `index.md` in each major folder (e.g., `/guide/index.md`, `/reference/index.md`) for clarity and easy navigation. - ---- +# Why Documentation is Important for Developers + +Documentation helps developers work efficiently and ensures projects run smoothly. Here’s why it’s crucial: + +1. **Knowledge Sharing**: It helps team members understand the system and communicate effectively, especially when new people join the project. + +2. **Code Maintenance**: Good documentation makes it easier to fix bugs, make updates, and keep the code consistent. + +3. **Project Longevity**: It ensures that project knowledge is preserved, so future developers can maintain or improve the code without confusion. + +4. **Troubleshooting**: Developers can quickly find solutions to problems or understand past decisions, saving time and reducing errors. + +5. **Testing and Quality**: Documentation helps ensure the right testing processes are followed, leading to better-quality code. + +6. **Efficiency**: It saves time by reducing the need to explain things repeatedly or search for answers. + +In short, internal documentation keeps projects organized, helps teams collaborate, and ensures the software can be maintained and improved over time. + +--- + +## Guide to Writing Modular Documentation for React Projects + +Modular documentation refers to organizing your documentation into independent, reusable sections or modules. Each module typically covers a specific part of your project, making it easier to update and navigate. + +In the context of React, modular documentation should cover both React components and the overall architecture of the app. + +### Split Documentation into Smaller Sections + +When documenting, break down each part of your codebase into its smallest logical unit: + +1. **Functions**: Explain its purpose, inputs (arguments), and outputs (returns). +2. **Components**: Detail props, their types, default values, and the UI they render. +3. **Utilities/Helpers**: Document what a utility does, its inputs, and outputs. +4. **APIs**: Cover the endpoint, request format, and expected response. + +Each section should have a consistent structure for easy understanding and reference. + +## Documenting Functions + +#### Structure for Documenting Functions + +1. **Function Name**: A short and descriptive name. +2. **Purpose**: Briefly explain what the function does. +3. **Inputs**: + - List each parameter. + - Include types and default values if applicable. +4. **Output**: Describe the return value and its type. +5. **Code Examples**: Provide a usage example. + +#### Example: Utility Function Documentation + +````markdown +## `formatDate` + +### Purpose + +The `formatDate` function converts a `Date` object into a human-readable string format. + +### Inputs + +| Parameter | Type | Default Value | Description | +| --------- | -------- | ------------- | -------------------------- | +| `date` | `Date` | - | The date object to format. | +| `locale` | `string` | `"en-US"` | The locale for formatting. | + +### Output + +Returns a `string` representing the formatted date. + +### Example + +```javascript +import { formatDate } from "./utils"; + +const date = new Date("2024-11-21"); +console.log(formatDate(date)); // Output: "November 21, 2024" +``` +```` + +## Documenting Components + +#### Structure for Documenting Components + +1. **Component Name**: Name of the React component. +2. **Purpose**: Explain what the component is for and its use case. +3. **Props**: + - List each prop. + - Include type, whether it’s required, and default value. +4. **Behavior**: Describe what the component does and any side effects. +5. **Output**: Explain what the component renders or returns. +6. **Code Examples**: Show how to use the component. + +#### Example: Component Documentation + +`````markdown +## `Button` + +### Purpose + +The `Button` component renders a clickable button with customizable styles and behavior. + +### Props + +| Prop Name | Type | Required | Default Value | Description | +| ---------- | ---------- | -------- | ------------- | ---------------------------------- | +| `label` | `string` | Yes | - | The text displayed on the button. | +| `onClick` | `function` | No | `() => {}` | The function to call when clicked. | +| `disabled` | `boolean` | No | `false` | Disables the button if true. | +| `style` | `object` | No | `{}` | Inline styles for the button. | + +### Behavior + +- If `disabled` is true, the button cannot be clicked. +- The `onClick` function will only be called when the button is enabled. + +### Output + +Renders a `; - }; - - export default Button; - ``` - -2. **Functions**: - - - Include a **detailed description** of what the function does. - - Specify the **parameters**, their types, and what they represent. - - Specify the **return type** and what it represents. - - **Example**: - - ```ts - /** - * Converts a date string to a readable format. - * - * @param {string} date - A date string in ISO format (e.g., "2024-11-21"). - * @returns {string} The formatted date (e.g., "November 21, 2024"). - */ - export const formatDate = (date: string): string => { - const options: Intl.DateTimeFormatOptions = { - year: "numeric", - month: "long", - day: "numeric", - }; - return new Date(date).toLocaleDateString(undefined, options); - }; - ``` - -3. **Commenting Standards**: - - - Each function and component should have a comment explaining: - - What it does. - - The props or parameters it accepts (including types). - - What it returns and why. - -4. **Why This Matters**: - - This structure helps us maintain a clean, modular codebase. It also makes the project easier to navigate for new and existing team members. - ---- - -## File Naming Guidelines - -To maintain consistency and professionalism in our codebase, we are standardizing the way we name files. This is crucial for readability, collaboration, and avoiding potential issues across different operating systems. -We are introducing a standardized **file naming convention** to maintain consistency across the codebase. Here are the key points: - -1. **File Naming**: - - - All file names must follow the **camelCase** convention (e.g., `headerComponent.tsx`, `calculateTotal.ts`). - - This ensures uniformity and avoids case sensitivity issues. - -2. **Pre-Commit Hook**: - - - A pre-commit hook will automatically rename files to camelCase if they don’t comply. - - Please double-check that your imports match the updated file names to avoid runtime errors. - -3. **What You Need to Do**: - - - Name files correctly in camelCase from the start. - - If a file is renamed during a commit, ensure all imports are updated to reflect the new name. - -4. **Why This Matters**: - - Consistent file naming improves readability and reduces issues when working in teams or across different operating systems. +## /temp/ files + +I’ve set up the repository to ignore all folders named `temp`. This is a space you can use for temporary or experimental files without worrying about affecting the application or pushing these files to Gitea. + +- **Purpose**: Use the `temp` folder to store temporary files, logs, or scripts for testing purposes. +- **Ignored by Git**: All `temp` folders are excluded from version control using the `.gitignore` rule `**/temp/`. These files will not be committed or pushed to the repository. +- **Best Practices**: Please avoid storing critical or shared files here. Use it for temporary work only, and clean up files when no longer needed. + +This should help us maintain a clean repository while giving everyone the freedom to experiment. + +--- + +## Standardized File Structure and Coding Guidelines + +To improve our codebase's readability, maintainability, and scalability, we’re adopting a standardized file structure and coding practices. Here’s a summary: + +1. **File Structure**: + + - **Components (`.tsx`)**: All files that return HTML/JSX will be React components with a `.tsx` extension. They should focus on UI logic and presentation. + + - **Purpose**: Files with the `.tsx` extension are reserved for React components that return JSX/HTML. + - **Location**: Components should be organized based on their purpose or scope within the application. Example: + ``` + src/ + components/ + Header.tsx + Footer.tsx + pages/ + Home.tsx + About.tsx + ``` + - **Naming Convention**: Component filenames should use PascalCase, matching the component name (e.g., `Header.tsx` for a `Header` component). + - **Example**: + + ```tsx + /** + * Header component that displays the application's navigation bar. + * + * @returns {JSX.Element} A navigation bar with links. + */ + const Header: React.FC = () => { + return ( +
+ +
+ ); + }; + + export default Header; + ``` + + - **Functions (`.ts`)**: All helper functions or business logic will go into `.ts` files, separate from the components. + - **Purpose**: Files with the `.ts` extension are for helper functions, utility logic, or other non-React code that does not return JSX/HTML. + - **Location**: Place utility files in a `utils` directory or within a directory relevant to their context. Example: + ``` + src/ + utils/ + calculateTotal.ts + formatDate.ts + hooks/ + useFetch.ts + ``` + - **Naming Convention**: Use camelCase for filenames that describe the primary function (e.g., `calculateTotal.ts` for a `calculateTotal` function). + - **Example**: + ```ts + /** + * Calculates the total price based on items and tax rate. + * + * @param {number[]} prices - Array of item prices. + * @param {number} taxRate - Tax rate as a decimal. + * @returns {number} Total price including tax. + */ + export const calculateTotal = ( + prices: number[], + taxRate: number + ): number => { + const subtotal = prices.reduce((sum, price) => sum + price, 0); + return subtotal + subtotal * taxRate; + }; + ``` + +--- + +## Commenting Standards + +To improve code readability and understanding, every function and component should include comments explaining its purpose, inputs, and outputs. Here’s how we’ll approach this: + +1. **React Components**: + + - Include a **high-level description** of what the component does. + - Specify the **props** it accepts, along with their types. + - Specify the **return type** (`JSX.Element` for React components). + + **Example**: + + ```tsx + /** + * Button component that triggers an action when clicked. + * + * @param {object} props - The props object. + * @param {string} props.label - The text to display on the button. + * @param {() => void} props.onClick - The callback function triggered when the button is clicked. + * @returns {JSX.Element} A styled button element. + */ + const Button: React.FC<{ label: string; onClick: () => void }> = ({ + label, + onClick, + }) => { + return ; + }; + + export default Button; + ``` + +2. **Functions**: + + - Include a **detailed description** of what the function does. + - Specify the **parameters**, their types, and what they represent. + - Specify the **return type** and what it represents. + + **Example**: + + ```ts + /** + * Converts a date string to a readable format. + * + * @param {string} date - A date string in ISO format (e.g., "2024-11-21"). + * @returns {string} The formatted date (e.g., "November 21, 2024"). + */ + export const formatDate = (date: string): string => { + const options: Intl.DateTimeFormatOptions = { + year: "numeric", + month: "long", + day: "numeric", + }; + return new Date(date).toLocaleDateString(undefined, options); + }; + ``` + +3. **Commenting Standards**: + + - Each function and component should have a comment explaining: + - What it does. + - The props or parameters it accepts (including types). + - What it returns and why. + +4. **Why This Matters**: + - This structure helps us maintain a clean, modular codebase. It also makes the project easier to navigate for new and existing team members. + +--- + +## File Naming Guidelines + +To maintain consistency and professionalism in our codebase, we are standardizing the way we name files. This is crucial for readability, collaboration, and avoiding potential issues across different operating systems. +We are introducing a standardized **file naming convention** to maintain consistency across the codebase. Here are the key points: + +1. **File Naming**: + + - All file names must follow the **camelCase** convention (e.g., `headerComponent.tsx`, `calculateTotal.ts`). + - This ensures uniformity and avoids case sensitivity issues. + +2. **Pre-Commit Hook**: + + - A pre-commit hook will automatically rename files to camelCase if they don’t comply. + - Please double-check that your imports match the updated file names to avoid runtime errors. + +3. **What You Need to Do**: + + - Name files correctly in camelCase from the start. + - If a file is renamed during a commit, ensure all imports are updated to reflect the new name. + +4. **Why This Matters**: + - Consistent file naming improves readability and reduces issues when working in teams or across different operating systems. diff --git a/app/docs/documents/projectStructure.md b/app/docs/documents/projectStructure.md index d3af88e..1e12346 100644 --- a/app/docs/documents/projectStructure.md +++ b/app/docs/documents/projectStructure.md @@ -1,107 +1,107 @@ -# Project Folder Structure - -This document provides a detailed description of the purpose of each folder in the project by root level, along with the folder hierarchy. - -## Folder Hierarchy - -``` -📁 src -├── 📁 assets -├── 📁 components -├── 📁 functions -├── 📁 hooks -├── 📁 modules -│ ├── 📁 builder -│ ├── 📁 simulation -│ └── 📁 visualization -├── 📁 services -├── 📁 store -├── 📁 styles -├── 📁 tests -├── 📁 types -├── 📁 utils -├── App.css -├── App.tsx -├── index.css -├── main.tsx -└── vite-env.d.ts -``` - ---- - -## Description of Each Folder - -### 📁 `src` -The root directory for all source code related to the application. - -#### 📁 `assets` -- **Purpose:** Contains static assets such as images, icons, fonts, or other resources. -- **Example:** - - `react.svg`: A static SVG file used in the project. - -#### 📁 `components` -- **Purpose:** Contains reusable React components, serving as building blocks for the user interface. -- **Example:** - - Buttons, modals, headers, and forms. - -#### 📁 `functions` -- **Purpose:** Stores pure functions or logic that can be reused across the application. -- **Example:** - - Utility functions for data transformation or computation. - -#### 📁 `hooks` -- **Purpose:** Holds custom React hooks for managing specific logic or behaviors. -- **Example:** - - Hooks for state management, API calls, or reusable effects. - -#### 📁 `modules` -- **Purpose:** Organizes high-level, feature-specific code into subdirectories. - - **📁 builder:** Manages functionalities and components related to building or configuring features. - - **📁 simulation:** Handles processes or logic related to simulations or dynamic scenarios. - - **📁 visualization:** Focuses on displaying data visually, such as charts, graphs, or interactive UI elements. - -#### 📁 `services` -- **Purpose:** Encapsulates external service interactions, such as API calls or library integrations. -- **Example:** - - REST API clients or authentication handlers. - -#### 📁 `store` -- **Purpose:** Contains state management logic and configurations for tools like Redux or Zustand. -- **Example:** - - Redux slices, context providers, or global state stores. - -#### 📁 `styles` -- **Purpose:** Includes global CSS, SCSS, or theming resources. -- **Example:** - - Global styles, theme variables, or resets. - -#### 📁 `tests` -- **Purpose:** Stores test files for unit testing, integration testing, and mock data. -- **Example:** - - Test files (`*.test.tsx`, `*.spec.ts`) or mock utilities. - -#### 📁 `types` -- **Purpose:** Contains shared TypeScript type definitions and interfaces. -- **Example:** - - Type declarations for props, data models, or API responses. - -#### 📁 `utils` -- **Purpose:** Includes general-purpose utility files that don’t fit into other specific folders. -- **Example:** - - Helper functions like debouncers or date formatters. - ---- - -## Root-Level Files - -### `App.tsx` -- **Purpose:** The root React component, initializing the main application layout and logic. - -### `index.css` -- **Purpose:** Contains global styles applied throughout the application. - -### `main.tsx` -- **Purpose:** The entry point of the app, rendering the React application and setting up the React DOM. - -### `vite-env.d.ts` -- **Purpose:** TypeScript environment configuration file for Vite. +# Project Folder Structure + +This document provides a detailed description of the purpose of each folder in the project by root level, along with the folder hierarchy. + +## Folder Hierarchy + +``` +📁 src +├── 📁 assets +├── 📁 components +├── 📁 functions +├── 📁 hooks +├── 📁 modules +│ ├── 📁 builder +│ ├── 📁 simulation +│ └── 📁 visualization +├── 📁 services +├── 📁 store +├── 📁 styles +├── 📁 tests +├── 📁 types +├── 📁 utils +├── App.css +├── App.tsx +├── index.css +├── main.tsx +└── vite-env.d.ts +``` + +--- + +## Description of Each Folder + +### 📁 `src` +The root directory for all source code related to the application. + +#### 📁 `assets` +- **Purpose:** Contains static assets such as images, icons, fonts, or other resources. +- **Example:** + - `react.svg`: A static SVG file used in the project. + +#### 📁 `components` +- **Purpose:** Contains reusable React components, serving as building blocks for the user interface. +- **Example:** + - Buttons, modals, headers, and forms. + +#### 📁 `functions` +- **Purpose:** Stores pure functions or logic that can be reused across the application. +- **Example:** + - Utility functions for data transformation or computation. + +#### 📁 `hooks` +- **Purpose:** Holds custom React hooks for managing specific logic or behaviors. +- **Example:** + - Hooks for state management, API calls, or reusable effects. + +#### 📁 `modules` +- **Purpose:** Organizes high-level, feature-specific code into subdirectories. + - **📁 builder:** Manages functionalities and components related to building or configuring features. + - **📁 simulation:** Handles processes or logic related to simulations or dynamic scenarios. + - **📁 visualization:** Focuses on displaying data visually, such as charts, graphs, or interactive UI elements. + +#### 📁 `services` +- **Purpose:** Encapsulates external service interactions, such as API calls or library integrations. +- **Example:** + - REST API clients or authentication handlers. + +#### 📁 `store` +- **Purpose:** Contains state management logic and configurations for tools like Redux or Zustand. +- **Example:** + - Redux slices, context providers, or global state stores. + +#### 📁 `styles` +- **Purpose:** Includes global CSS, SCSS, or theming resources. +- **Example:** + - Global styles, theme variables, or resets. + +#### 📁 `tests` +- **Purpose:** Stores test files for unit testing, integration testing, and mock data. +- **Example:** + - Test files (`*.test.tsx`, `*.spec.ts`) or mock utilities. + +#### 📁 `types` +- **Purpose:** Contains shared TypeScript type definitions and interfaces. +- **Example:** + - Type declarations for props, data models, or API responses. + +#### 📁 `utils` +- **Purpose:** Includes general-purpose utility files that don’t fit into other specific folders. +- **Example:** + - Helper functions like debouncers or date formatters. + +--- + +## Root-Level Files + +### `App.tsx` +- **Purpose:** The root React component, initializing the main application layout and logic. + +### `index.css` +- **Purpose:** Contains global styles applied throughout the application. + +### `main.tsx` +- **Purpose:** The entry point of the app, rendering the React application and setting up the React DOM. + +### `vite-env.d.ts` +- **Purpose:** TypeScript environment configuration file for Vite. diff --git a/app/docs/index.html b/app/docs/index.html index 5dcb9ac..5f0c098 100644 --- a/app/docs/index.html +++ b/app/docs/index.html @@ -1,97 +1,97 @@ - - - - - - Documentation - - - - - - - - - - - -
- - - - - - - - - - - - - - + + + + + + Documentation + + + + + + + + + + + +
+ + + + + + + + + + + + + + diff --git a/app/nginx.conf b/app/nginx.conf index a6265e3..6c3bbfb 100644 --- a/app/nginx.conf +++ b/app/nginx.conf @@ -1,14 +1,14 @@ -server { - listen 3000; - server_name localhost; - - root /usr/share/nginx/html; - index index.html; - - location / { - try_files $uri /index.html; - } - - # Redirect 404 errors to index.html (for React Router) - error_page 404 /index.html; +server { + listen 3000; + server_name localhost; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri /index.html; + } + + # Redirect 404 errors to index.html (for React Router) + error_page 404 /index.html; } \ No newline at end of file diff --git a/app/package-lock.json b/app/package-lock.json index d9af69f..bac88d5 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -1,3 +1,4 @@ +<<<<<<< HEAD { "name": "dwinzo-beta", "version": "0.1.0", @@ -22264,3 +22265,22271 @@ } } } +======= +{ + "name": "dwinzo-beta", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dwinzo-beta", + "version": "0.1.0", + "dependencies": { + "@react-three/csg": "^3.2.0", + "@react-three/drei": "^9.113.0", + "@react-three/fiber": "^8.17.7", + "@react-three/postprocessing": "^2.16.3", + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^13.5.0", + "@turf/turf": "^7.1.0", + "@types/jest": "^27.5.2", + "@types/react": "^18.3.5", + "@types/react-dom": "^18.3.0", + "@use-gesture/react": "^10.3.1", + "chart.js": "^4.4.8", + "glob": "^11.0.0", + "gsap": "^3.12.5", + "leva": "^0.10.0", + "mqtt": "^5.10.4", + "postprocessing": "^6.36.4", + "prompt-sync": "^4.2.0", + "react": "^18.3.1", + "react-chartjs-2": "^5.3.0", + "react-dom": "^18.3.1", + "react-router-dom": "^7.4.0", + "react-scripts": "5.0.1", + "react-toastify": "^10.0.5", + "sass": "^1.78.0", + "socket.io-client": "^4.8.1", + "three": "^0.168.0", + "typescript": "^4.9.5", + "web-vitals": "^2.1.4", + "zustand": "^5.0.0-rc.2" + }, + "devDependencies": { + "@types/node": "^22.9.1", + "@types/three": "^0.169.0", + "cypress": "^13.14.2", + "dotenv": "^16.4.5", + "husky": "^9.1.6", + "ts-node": "^10.9.2" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.1.tgz", + "integrity": "sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ==" + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.9.tgz", + "integrity": "sha512-5UXfgpK0j0Xr/xIdgdLEhOFxaDZ0bRPWJJchRpqOSur/3rZoPbqqki5mm0p4NE2cs28krBEiSM2MB7//afRSQQ==", + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "dependencies": { + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz", + "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "dependencies": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz", + "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", + "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", + "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", + "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "dependencies": { + "@babel/types": "^7.26.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz", + "integrity": "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-decorators": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz", + "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", + "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", + "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", + "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", + "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", + "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.9.tgz", + "integrity": "sha512-/VVukELzPDdci7UUsWQaSkhgnjIWXnIyRpM02ldxaVoFK96c41So8JcKT3m0gYjyv7j5FNPGS5vfELrWalkbDA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-flow": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", + "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", + "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", + "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.9.tgz", + "integrity": "sha512-Ncw2JFsJVuvfRsa2lSHiC55kETQVLSnsYGQ1JDDwkUeWGTL/8Tom8aLTnlqgoeuopWrbbGndrc9AlLYrIosrow==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz", + "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", + "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz", + "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz", + "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", + "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", + "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", + "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", + "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz", + "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", + "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", + "dependencies": { + "@babel/compat-data": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.25.9", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.25.9", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.25.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.25.9", + "@babel/plugin-transform-typeof-symbol": "^7.25.9", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.38.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.9.tgz", + "integrity": "sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-react-display-name": "^7.25.9", + "@babel/plugin-transform-react-jsx": "^7.25.9", + "@babel/plugin-transform-react-jsx-development": "^7.25.9", + "@babel/plugin-transform-react-pure-annotations": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@csstools/normalize.css": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.1.1.tgz", + "integrity": "sha512-YAYeJ+Xqh7fUou1d1j9XHl44BmsuThiTr4iNrgCQ3J27IbhXsxXDGZ1cXv8Qvs99d4rBbLiSKy3+WZiet32PcQ==" + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", + "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@cypress/request": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.6.tgz", + "integrity": "sha512-fi0eVdCOtKu5Ed6+E8mYxUF6ZTFJDZvHogCBelM0xVXmrDEkyM22gRArQzq1YcHPm1V47Vf/iAD+WgVdUlJCGg==", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~4.0.0", + "http-signature": "~1.4.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "6.13.0", + "safe-buffer": "^5.1.2", + "tough-cookie": "^5.0.0", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@cypress/request/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "dependencies": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + } + }, + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.7.3.tgz", + "integrity": "sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg==", + "license": "MIT" + }, + "node_modules/@floating-ui/dom": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.5.4.tgz", + "integrity": "sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^0.7.3" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-0.7.2.tgz", + "integrity": "sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^0.5.3", + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dependencies": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/reporters/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dependencies": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/@jest/transform/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.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==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "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==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@kurkle/color": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", + "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", + "license": "MIT" + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" + }, + "node_modules/@mediapipe/tasks-vision": { + "version": "0.10.17", + "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.17.tgz", + "integrity": "sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg==" + }, + "node_modules/@monogrid/gainmap-js": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@monogrid/gainmap-js/-/gainmap-js-3.0.6.tgz", + "integrity": "sha512-ireqJg7cw0tUn/JePDG8rAL7RyXgUKSDbjYdiygkrnye1WuKGLAWDBwF/ICwCwJ9iZBAF5caU8gSu+c34HLGdQ==", + "dependencies": { + "promise-worker-transferable": "^1.0.4" + }, + "peerDependencies": { + "three": ">= 0.159.0" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", + "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.0", + "@parcel/watcher-darwin-arm64": "2.5.0", + "@parcel/watcher-darwin-x64": "2.5.0", + "@parcel/watcher-freebsd-x64": "2.5.0", + "@parcel/watcher-linux-arm-glibc": "2.5.0", + "@parcel/watcher-linux-arm-musl": "2.5.0", + "@parcel/watcher-linux-arm64-glibc": "2.5.0", + "@parcel/watcher-linux-arm64-musl": "2.5.0", + "@parcel/watcher-linux-x64-glibc": "2.5.0", + "@parcel/watcher-linux-x64-musl": "2.5.0", + "@parcel/watcher-win32-arm64": "2.5.0", + "@parcel/watcher-win32-ia32": "2.5.0", + "@parcel/watcher-win32-x64": "2.5.0" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", + "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", + "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", + "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", + "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", + "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", + "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", + "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", + "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", + "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", + "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", + "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", + "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", + "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz", + "integrity": "sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ==", + "dependencies": { + "ansi-html": "^0.0.9", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.4", + "schema-utils": "^4.2.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "@types/webpack": "4.x || 5.x", + "react-refresh": ">=0.10.0 <1.0.0", + "sockjs-client": "^1.4.0", + "type-fest": ">=0.17.0 <5.0.0", + "webpack": ">=4.43.0 <6.0.0", + "webpack-dev-server": "3.x || 4.x || 5.x", + "webpack-hot-middleware": "2.x", + "webpack-plugin-serve": "0.x || 1.x" + }, + "peerDependenciesMeta": { + "@types/webpack": { + "optional": true + }, + "sockjs-client": { + "optional": true + }, + "type-fest": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + }, + "webpack-hot-middleware": { + "optional": true + }, + "webpack-plugin-serve": { + "optional": true + } + } + }, + "node_modules/@radix-ui/primitive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz", + "integrity": "sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.2.tgz", + "integrity": "sha512-fqYwhhI9IarZ0ll2cUSfKuXHlJK0qE4AfnRrPBbRwEH/4mGQn04/QFGomLi8TXWIdv9WJk//KgGm+aDxVIr1wA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.2" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz", + "integrity": "sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.0.tgz", + "integrity": "sha512-1pVM9RfOQ+n/N5PJK33kRSKsr1glNxomxONs5c49MliinBY6Yw2Q995qfBUUo0/Mbg05B/sGA0gkgPI7kmSHBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.3.tgz", + "integrity": "sha512-nXZOvFjOuHS1ovumntGV7NNoLaEp9JEvTht3MBjP44NSW5hUKj/8OnfN3+8WmB+CEhN44XaGhpHoSsUIEl5P7Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-primitive": "1.0.2", + "@radix-ui/react-use-callback-ref": "1.0.0", + "@radix-ui/react-use-escape-keydown": "1.0.2" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.0.tgz", + "integrity": "sha512-Q6iAB/U7Tq3NTolBBQbHTgclPmGWE3OlktGGqrClPozSw4vkQ1DfQAOtzgRPecKsMdJINE05iaoDUG8tRzCBjw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.1.tgz", + "integrity": "sha512-keYDcdMPNMjSC8zTsZ8wezUMiWM9Yj14wtF3s0PTIs9srnEPC9Kt2Gny1T3T81mmSeyDjZxsD9N5WCwNNb712w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@floating-ui/react-dom": "0.7.2", + "@radix-ui/react-arrow": "1.0.2", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-primitive": "1.0.2", + "@radix-ui/react-use-callback-ref": "1.0.0", + "@radix-ui/react-use-layout-effect": "1.0.0", + "@radix-ui/react-use-rect": "1.0.0", + "@radix-ui/react-use-size": "1.0.0", + "@radix-ui/rect": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.2.tgz", + "integrity": "sha512-swu32idoCW7KA2VEiUZGBSu9nB6qwGdV6k6HYhUoOo3M1FFpD+VgLzUqtt3mwL1ssz7r2x8MggpLSQach2Xy/Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.2" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.0.tgz", + "integrity": "sha512-A+6XEvN01NfVWiKu38ybawfHsBjWum42MRPnEuqPsBZ4eV7e/7K321B5VgYMPv3Xx5An6o1/l9ZuDBgmcmWK3w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-use-layout-effect": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.2.tgz", + "integrity": "sha512-zY6G5Qq4R8diFPNwtyoLRZBxzu1Z+SXMlfYpChN7Dv8gvmx9X3qhDqiLWvKseKVJMuedFeU/Sa0Sy/Ia+t06Dw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.1" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.1.tgz", + "integrity": "sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.5.tgz", + "integrity": "sha512-cDKVcfzyO6PpckZekODJZDe5ZxZ2fCZlzKzTmPhe4mX9qTHRfLcKgqb0OKf22xLwDequ2tVleim+ZYx3rabD5w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-dismissable-layer": "1.0.3", + "@radix-ui/react-id": "1.0.0", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", + "@radix-ui/react-presence": "1.0.0", + "@radix-ui/react-primitive": "1.0.2", + "@radix-ui/react-slot": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.0", + "@radix-ui/react-visually-hidden": "1.0.2" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.0.tgz", + "integrity": "sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.0.tgz", + "integrity": "sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz", + "integrity": "sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.0.tgz", + "integrity": "sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz", + "integrity": "sha512-TB7pID8NRMEHxb/qQJpvSt3hQU4sqNPM1VCTjTRjEOa7cEop/QMuq8S6fb/5Tsz64kqSvB9WnwsDHtjnrM9qew==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/rect": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.0.tgz", + "integrity": "sha512-imZ3aYcoYCKhhgNpkNDh/aTiU05qw9hX+HHI1QDBTyIlcFjgeFlKKySNGMwTp7nYFLQg/j0VA2FmCY4WPDDHMg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.2.tgz", + "integrity": "sha512-qirnJxtYn73HEk1rXL12/mXnu2rwsNHDID10th2JGtdK25T9wX+mxRmGt7iPSahw512GbZOc0syZX1nLQGoEOg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.2" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.0.tgz", + "integrity": "sha512-d0O68AYy/9oeEy1DdC07bz1/ZXX+DqCskRd3i4JzLSTXwefzaepQrKjXC7aNM8lTHjFLDO0pDgaEiQ7jEk+HVg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@react-spring/animated": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.5.tgz", + "integrity": "sha512-Tqrwz7pIlsSDITzxoLS3n/v/YCUHQdOIKtOJf4yL6kYVSDTSmVK1LI1Q3M/uu2Sx4X3pIWF3xLUhlsA6SPNTNg==", + "dependencies": { + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/core": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.5.tgz", + "integrity": "sha512-rmEqcxRcu7dWh7MnCcMXLvrf6/SDlSokLaLTxiPlAYi11nN3B5oiCUAblO72o+9z/87j2uzxa2Inm8UbLjXA+w==", + "dependencies": { + "@react-spring/animated": "~9.7.5", + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/rafz": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.5.tgz", + "integrity": "sha512-5ZenDQMC48wjUzPAm1EtwQ5Ot3bLIAwwqP2w2owG5KoNdNHpEJV263nGhCeKKmuA3vG2zLLOdu3or6kuDjA6Aw==" + }, + "node_modules/@react-spring/shared": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.5.tgz", + "integrity": "sha512-wdtoJrhUeeyD/PP/zo+np2s1Z820Ohr/BbuVYv+3dVLW7WctoiN7std8rISoYoHpUXtbkpesSKuPIw/6U1w1Pw==", + "dependencies": { + "@react-spring/rafz": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/three": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.7.5.tgz", + "integrity": "sha512-RxIsCoQfUqOS3POmhVHa1wdWS0wyHAUway73uRLp3GAL5U2iYVNdnzQsep6M2NZ994BlW8TcKuMtQHUqOsy6WA==", + "dependencies": { + "@react-spring/animated": "~9.7.5", + "@react-spring/core": "~9.7.5", + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "peerDependencies": { + "@react-three/fiber": ">=6.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "three": ">=0.126" + } + }, + "node_modules/@react-spring/types": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.5.tgz", + "integrity": "sha512-HVj7LrZ4ReHWBimBvu2SKND3cDVUPWKLqRTmWe/fNY6o1owGOX0cAHbdPDTMelgBlVbrTKrre6lFkhqGZErK/g==" + }, + "node_modules/@react-three/csg": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@react-three/csg/-/csg-3.2.0.tgz", + "integrity": "sha512-POnakTYaJqmqKsk9Q23oCL78JmaitN2+s/ciOHDK8dQu6GsSa2eMzlhR7J7kI9VdjmV/cW2cRz9XJEWNJ4XmfA==", + "dependencies": { + "three-bvh-csg": "^0.0.16", + "three-mesh-bvh": "^0.6.8" + } + }, + "node_modules/@react-three/drei": { + "version": "9.117.3", + "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.117.3.tgz", + "integrity": "sha512-SnL8d17qO1cFXGVlDHhp+Oa9VZPwwOeibLHri5KNRARKOPv2+R71Sl84RTU9samBI2+1EaGJFciDvRgQnq+JOA==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mediapipe/tasks-vision": "0.10.17", + "@monogrid/gainmap-js": "^3.0.6", + "@react-spring/three": "~9.7.5", + "@use-gesture/react": "^10.3.1", + "camera-controls": "^2.9.0", + "cross-env": "^7.0.3", + "detect-gpu": "^5.0.56", + "glsl-noise": "^0.0.0", + "hls.js": "^1.5.17", + "maath": "^0.10.8", + "meshline": "^3.3.1", + "react-composer": "^5.0.3", + "stats-gl": "^2.2.8", + "stats.js": "^0.17.0", + "suspend-react": "^0.1.3", + "three-mesh-bvh": "^0.7.8", + "three-stdlib": "^2.34.0", + "troika-three-text": "^0.52.0", + "tunnel-rat": "^0.1.2", + "utility-types": "^3.11.0", + "uuid": "^9.0.1", + "zustand": "^5.0.1" + }, + "peerDependencies": { + "@react-three/fiber": ">=8.0", + "react": ">=18.0", + "react-dom": ">=18.0", + "three": ">=0.137" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/@react-three/drei/node_modules/three-mesh-bvh": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.8.tgz", + "integrity": "sha512-BGEZTOIC14U0XIRw3tO4jY7IjP7n7v24nv9JXS1CyeVRWOCkcOMhRnmENUjuV39gktAw4Ofhr0OvIAiTspQrrw==", + "deprecated": "Deprecated due to three.js version incompatibility. Please use v0.8.0, instead.", + "peerDependencies": { + "three": ">= 0.151.0" + } + }, + "node_modules/@react-three/fiber": { + "version": "8.17.10", + "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.17.10.tgz", + "integrity": "sha512-S6bqa4DqUooEkInYv/W+Jklv2zjSYCXAhm6qKpAQyOXhTEt5gBXnA7W6aoJ0bjmp9pAeaSj/AZUoz1HCSof/uA==", + "dependencies": { + "@babel/runtime": "^7.17.8", + "@types/debounce": "^1.2.1", + "@types/react-reconciler": "^0.26.7", + "@types/webxr": "*", + "base64-js": "^1.5.1", + "buffer": "^6.0.3", + "debounce": "^1.2.1", + "its-fine": "^1.0.6", + "react-reconciler": "^0.27.0", + "scheduler": "^0.21.0", + "suspend-react": "^0.1.3", + "zustand": "^3.7.1" + }, + "peerDependencies": { + "expo": ">=43.0", + "expo-asset": ">=8.4", + "expo-file-system": ">=11.0", + "expo-gl": ">=11.0", + "react": ">=18.0", + "react-dom": ">=18.0", + "react-native": ">=0.64", + "three": ">=0.133" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + }, + "expo-asset": { + "optional": true + }, + "expo-file-system": { + "optional": true + }, + "expo-gl": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/@react-three/fiber/node_modules/zustand": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", + "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/@react-three/postprocessing": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/@react-three/postprocessing/-/postprocessing-2.16.3.tgz", + "integrity": "sha512-ftodXpUsy0/mzn0KqyV7MBau71dD9C5UOFnB3kHhCLNoxjKYQWZa9do0olJTSkl3owYXRfNHcLriK1Xn8wxZJw==", + "dependencies": { + "buffer": "^6.0.3", + "maath": "^0.6.0", + "n8ao": "^1.6.6", + "postprocessing": "^6.32.1", + "three-stdlib": "^2.23.4" + }, + "peerDependencies": { + "@react-three/fiber": ">=8.0", + "react": ">=18.0", + "three": ">= 0.138.0" + } + }, + "node_modules/@react-three/postprocessing/node_modules/maath": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/maath/-/maath-0.6.0.tgz", + "integrity": "sha512-dSb2xQuP7vDnaYqfoKzlApeRcR2xtN8/f7WV/TMAkBC8552TwTLtOO0JTcSygkYMjNDPoo6V01jTw/aPi4JrMw==", + "peerDependencies": { + "@types/three": ">=0.144.0", + "three": ">=0.144.0" + } + }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "node_modules/@stitches/react": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@stitches/react/-/react-1.2.8.tgz", + "integrity": "sha512-9g9dWI4gsSVe8bNLlb+lMkBYsnIKCZTmvqvDG+Avnn69XfmHZKiaMrx7cgTaddq7aTPPmXiTsbFcUy0xgI4+wA==", + "license": "MIT", + "peerDependencies": { + "react": ">= 16.3.0" + } + }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", + "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", + "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", + "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", + "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", + "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", + "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", + "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", + "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", + "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", + "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", + "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/core": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", + "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", + "dependencies": { + "@svgr/plugin-jsx": "^5.5.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", + "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", + "dependencies": { + "@babel/types": "^7.12.6" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", + "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "dependencies": { + "@babel/core": "^7.12.3", + "@svgr/babel-preset": "^5.5.0", + "@svgr/hast-util-to-babel-ast": "^5.5.0", + "svg-parser": "^2.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", + "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "dependencies": { + "cosmiconfig": "^7.0.0", + "deepmerge": "^4.2.2", + "svgo": "^1.2.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", + "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/plugin-transform-react-constant-elements": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-react": "^7.12.5", + "@svgr/core": "^5.5.0", + "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-svgo": "^5.5.0", + "loader-utils": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", + "integrity": "sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==", + "dependencies": { + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=8", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", + "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.5.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/@testing-library/dom": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", + "integrity": "sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@testing-library/react/node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/@testing-library/user-event": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", + "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@turf/along": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/along/-/along-7.1.0.tgz", + "integrity": "sha512-WLgBZJ/B6CcASF6WL7M+COtHlVP0hBrMbrtKyF7KBlicwRuijJZXDtEQA5oLgr+k1b2HqGN+UqH2A0/E719enQ==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/angle": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/angle/-/angle-7.1.0.tgz", + "integrity": "sha512-YMHEV/YrARsWgWoQuXEWrQMsvB8z67nTMw2eiLZ883V7jwkhWQGvCW6W+/mGgsWQdHppjCZNcKryryhD2GRWVA==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/area": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/area/-/area-7.1.0.tgz", + "integrity": "sha512-w91FEe02/mQfMPRX2pXua48scFuKJ2dSVMF2XmJ6+BJfFiCPxp95I3+Org8+ZsYv93CDNKbf0oLNEPnuQdgs2g==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-7.1.0.tgz", + "integrity": "sha512-PdWPz9tW86PD78vSZj2fiRaB8JhUHy6piSa/QXb83lucxPK+HTAdzlDQMTKj5okRCU8Ox/25IR2ep9T8NdopRA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox-clip": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bbox-clip/-/bbox-clip-7.1.0.tgz", + "integrity": "sha512-PhZubKCzF/afwStUzODqOJluiCbCw244lCtVhXA9F+Pgkhvk8KvbFdgpPquOZ45OwuktrchSB28BrBkSBiadHw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bbox-polygon": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bbox-polygon/-/bbox-polygon-7.1.0.tgz", + "integrity": "sha512-fvZB09ErCZOVlWVDop836hmpKaGUmfXnR9naMhS73A/8nn4M3hELbQtMv2R8gXj7UakXCuxS/i9erdpDFZ2O+g==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bearing": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bearing/-/bearing-7.1.0.tgz", + "integrity": "sha512-X5lackrZ6FW+YhgjWxwVFRgWD1j4xm4t5VvE6EE6v/1PVaHQ5OCjf6u1oaLx5LSG+gaHUhjTlAHrn9MYPFaeTA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/bezier-spline": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/bezier-spline/-/bezier-spline-7.1.0.tgz", + "integrity": "sha512-bhBY70bcVYJEosuW7B/TFtnE5rmPTTpxmJvljhGC0eyM84oNVv7apDBuseb5KdlTOOBIvdD9nIE4qV8lmplp6w==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-clockwise": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-7.1.0.tgz", + "integrity": "sha512-H5DYno+gHwZx+VaiC8DUBZXZQlxYecdSvqCfCACWi1uMsKvlht/O+xy65hz2P57lk2smlcV+1ETFVxJlEZduYg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-concave": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-concave/-/boolean-concave-7.1.0.tgz", + "integrity": "sha512-IFCN25DI+hvngxIsv4+MPuRJQRl/Lz/xnZgpH82leCn4Jqn5wW7KqKFMz7G4GoKK+93cK5/6ioAxY7hVWBXxJw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-contains": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-contains/-/boolean-contains-7.1.0.tgz", + "integrity": "sha512-ldy4j1/RVChYTYjEb4wWaE/JyF1jA87WpsB4eVLic6OcAYJGs7POF1kfKbcdkJJiRBmhI3CXNA+u+m9y4Z/j3g==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-crosses": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-crosses/-/boolean-crosses-7.1.0.tgz", + "integrity": "sha512-LK8UM3AENycuGinLCDaL0QSznGMnD0XsjFDGnY4KehshiL5Zd8ZsPyKmHOPygUJT9DWeH69iLx459lOc+5Vj2w==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/polygon-to-line": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-disjoint": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-disjoint/-/boolean-disjoint-7.1.0.tgz", + "integrity": "sha512-JapOG03kOCoGeYMWgTQjEifhr1nUoK4Os2cX0iC5X9kvZF4qCHeruX8/rffBQDx7PDKQKusSTXq8B1ISFi0hOw==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/polygon-to-line": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-equal": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-equal/-/boolean-equal-7.1.0.tgz", + "integrity": "sha512-deghtFMApc7fNsdXtZdgYR4gsU+TVfowcv666nrvZbPPsXL6NTYGBhDFmYXsJ8gPTCGT9uT0WXppdgT8diWOxA==", + "dependencies": { + "@turf/clean-coords": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "geojson-equality-ts": "^1.0.2", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-intersects": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-intersects/-/boolean-intersects-7.1.0.tgz", + "integrity": "sha512-gpksWbb0RT+Z3nfqRfoACY3KEFyv2BPaxJ3L76PH67DhHZviq3Nfg85KYbpuhS64FSm+9tXe4IaKn6EjbHo20g==", + "dependencies": { + "@turf/boolean-disjoint": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-overlap": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-overlap/-/boolean-overlap-7.1.0.tgz", + "integrity": "sha512-mJRN0X8JiPm8eDZk5sLvIrsP03A2GId6ijx4VgSE1AvHwV6qB561KlUbWxga2AScocIfv/y/qd2OCs+/TQSZcg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/line-overlap": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "geojson-equality-ts": "^1.0.2", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-parallel": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-parallel/-/boolean-parallel-7.1.0.tgz", + "integrity": "sha512-tA84Oux0X91CxUc6c/lZph5W9wUZGNT4fxFOg5Gp1IMTSwtxSYL1LMvKsr/VmMnwdOUkNcqAgU06+t4wBLtDfg==", + "dependencies": { + "@turf/clean-coords": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/line-segment": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-point-in-polygon": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.1.0.tgz", + "integrity": "sha512-mprVsyIQ+ijWTZwbnO4Jhxu94ZW2M2CheqLiRTsGJy0Ooay9v6Av5/Nl3/Gst7ZVXxPqMeMaFYkSzcTc87AKew==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "point-in-polygon-hao": "^1.1.0", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-point-on-line": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-point-on-line/-/boolean-point-on-line-7.1.0.tgz", + "integrity": "sha512-Kd83EjeTyY4kVMAhcW3Lb8aChwh24BUIhmpE9Or8M+ETNsFGzn9M7qtIySJHLRzKAL3letvWSKXKQPuK1AhAzg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-touches": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-touches/-/boolean-touches-7.1.0.tgz", + "integrity": "sha512-qN4LCs3RfVtNAAdn5GpsUFBqoZyAaK9UzSnGSh67GP9sy5M8MEHwM/HAJ5zGWJqQADrczI3U6BRWGLcGfGSz3Q==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-valid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-valid/-/boolean-valid-7.1.0.tgz", + "integrity": "sha512-zq1QCfQEyn+piHlvxxDifjmsJn2xl53i4mnKFYdMQI/i09XiX+Fi/MVM3i2hf3D5AsEPsud8Tk7C7rWNCm4nVw==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/boolean-crosses": "^7.1.0", + "@turf/boolean-disjoint": "^7.1.0", + "@turf/boolean-overlap": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@types/geojson": "^7946.0.10", + "geojson-polygon-self-intersections": "^1.2.1", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/boolean-within": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-within/-/boolean-within-7.1.0.tgz", + "integrity": "sha512-pgXgKCzYHssADQ1nClB1Q9aWI/dE1elm2jy3B5X59XdoFXKrKDZA+gCHYOYgp2NGO/txzVfl3UKvnxIj54Fa4w==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/buffer": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/buffer/-/buffer-7.1.0.tgz", + "integrity": "sha512-QM3JiCMYA19k5ouO8wJtvICX3Y8XntxVpDfHSKhFFidZcCkMTR2PWWOpwS6EoL3t75rSKw/FOLIPLZGtIu963w==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/center": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/jsts": "^2.7.1", + "@turf/meta": "^7.1.0", + "@turf/projection": "^7.1.0", + "@types/geojson": "^7946.0.10", + "d3-geo": "1.7.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/center/-/center-7.1.0.tgz", + "integrity": "sha512-p9AvBMwNZmRg65kU27cGKHAUQnEcdz8Y7f/i5DvaMfm4e8zmawr+hzPKXaUpUfiTyLs8Xt2W9vlOmNGyH+6X3w==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center-mean": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/center-mean/-/center-mean-7.1.0.tgz", + "integrity": "sha512-NQZB1LUVsyAD+p0+D4huzX2XVnfVx1yEEI9EX602THmi+g+nkge4SK9OMV11ov/Tv8JJ6aVNVPo/cy1vm/LCIQ==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center-median": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/center-median/-/center-median-7.1.0.tgz", + "integrity": "sha512-jx4/Ql5+v41Cd0J/gseNCUbLTzWUT2LUaiXn8eFWDrvmEgqHIx7KJcGcJd5HzV+9zJwng4AXxyh5NMvUR0NjwA==", + "dependencies": { + "@turf/center-mean": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/center-of-mass": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/center-of-mass/-/center-of-mass-7.1.0.tgz", + "integrity": "sha512-j38oBlj7LBoCjZbrIo8EoHVGhk7UQmMLQ1fe8ZPAF9pd05XEL1qxyHKZKdQ/deGISiaEhXCyfLNrKAHAuy25RA==", + "dependencies": { + "@turf/centroid": "^7.1.0", + "@turf/convex": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/centroid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-7.1.0.tgz", + "integrity": "sha512-1Y1b2l+ZB1CZ+ITjUCsGqC4/tSjwm/R4OUfDztVqyyCq/VvezkLmTNqvXTGXgfP0GXkpv68iCfxF5M7QdM5pJQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/circle": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/circle/-/circle-7.1.0.tgz", + "integrity": "sha512-6qhF1drjwH0Dg3ZB9om1JkWTJfAqBcbtIrAj5UPlrAeHP87hGoCO2ZEsFEAL9Q18vntpivT89Uho/nqQUjJhYw==", + "dependencies": { + "@turf/destination": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clean-coords": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/clean-coords/-/clean-coords-7.1.0.tgz", + "integrity": "sha512-q1U8UbRVL5cRdwOlNjD8mad8pWjFGe0s4ihg1pSiVNq7i47WASJ3k20yZiUFvuAkyNjV0rZ/A7Jd7WzjcierFg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clone": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-7.1.0.tgz", + "integrity": "sha512-5R9qeWvL7FDdBIbEemd0eCzOStr09oburDvJ1hRiPCFX6rPgzcZBQ0gDmZzoF4AFcNLb5IwknbLZjVLaUGWtFA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clusters": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/clusters/-/clusters-7.1.0.tgz", + "integrity": "sha512-7CY3Ai+5V6q2O9/IgqLpJQrmrTy7aUJjTW1iRan8Tz3WixvxyJHeS3iyRy8Oc0046chQIaHLtyTgKVt2QdsPSA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clusters-dbscan": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/clusters-dbscan/-/clusters-dbscan-7.1.0.tgz", + "integrity": "sha512-BmrBTOEaKN5FIED6b3yb3V3ejfK0A2Q3pT9/ji3mcRLJiBaRGeiN5V6gtGXe7PeMYdoqhHykU5Ye2uUtREWRdQ==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/clusters-kmeans": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/clusters-kmeans/-/clusters-kmeans-7.1.0.tgz", + "integrity": "sha512-M8cCqR6iE1jDSUF/UU9QdPUFrobZS2fo59TfF1IRHZ2G1EjbcK4GzZcUfmQS6DZraGudYutpMYIuNdm1dPMqdQ==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "skmeans": "0.9.7", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/collect": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/collect/-/collect-7.1.0.tgz", + "integrity": "sha512-6indMWLiKeBh4AsioNeFeFnO0k9U5CBsWAFEje6tOEFI4c+P7LF9mNA9z91H8KkrhegR9XNO5Vm2rmdY63aYXw==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/combine": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/combine/-/combine-7.1.0.tgz", + "integrity": "sha512-Xl7bGKKjgzIq2T/IemS6qnIykyuxU6cMxKtz+qLeWJGoNww/BllwxXePSV+dWRPXZTFFj96KIhBXAW0aUjAQKQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/concave": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/concave/-/concave-7.1.0.tgz", + "integrity": "sha512-aSid53gYRee4Tjc4pfeI3KI+RoBUnL/hRMilxIPduagTgZZS+cvvk01OQWBKm5UTVfHRGuy0XIqnK8y9RFinDQ==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/tin": "^7.1.0", + "@types/geojson": "^7946.0.10", + "topojson-client": "3.x", + "topojson-server": "3.x", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/convex": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/convex/-/convex-7.1.0.tgz", + "integrity": "sha512-w9fUMZYE36bLrEWEj7L7aVMCB7NBtr2o8G+avRvUIwF4DPqbtcjlcZE9EEBfq44uYdn+/Pke6Iq42T/zyD/cpg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "concaveman": "^1.2.1", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/destination": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/destination/-/destination-7.1.0.tgz", + "integrity": "sha512-97XuvB0iaAiMg86hrnZ529WwP44TQAA9mmI5PMlchACiA4LFrEtWjjDzvO6234coieoqhrw6dZYcJvd5O2PwrQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/difference": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/difference/-/difference-7.1.0.tgz", + "integrity": "sha512-+JVzdskICQ8ULKQ9CpWUM5kBvoXxN4CO78Ez/Ki3/7NXl7+HM/nb12B0OyM8hkJchpb8TsOi0YwyJiKMqEpTBA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "polygon-clipping": "^0.15.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/dissolve": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/dissolve/-/dissolve-7.1.0.tgz", + "integrity": "sha512-fyOnCSYVUZ8SF9kt9ROnQYlkJTE0hpWSoWwbMZQCAR7oVZVPiuPq7eIbzTP+k5jzEAnofsqoGs5qVDTjHcWMiw==", + "dependencies": { + "@turf/flatten": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "polygon-clipping": "^0.15.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/distance": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/distance/-/distance-7.1.0.tgz", + "integrity": "sha512-hhNHhxCHB3ddzAGCNY4BtE29OZh+DAJPvUapQz+wOjISnlwvMcwLKvslgHWSYF536QDVe/93FEU2q67+CsZTPA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/distance-weight": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/distance-weight/-/distance-weight-7.1.0.tgz", + "integrity": "sha512-8m6s4y8Yyt6r3itf44yAJjXC+62UkrkhOpskIfaE0lHcBcvZz9wjboHoBf3bS4l/42E4StcanbFZdjOpODAdZw==", + "dependencies": { + "@turf/centroid": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/ellipse": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/ellipse/-/ellipse-7.1.0.tgz", + "integrity": "sha512-AfOahUmStDExWGPg8ZWxxkgom+fdJs7Mn9DzZH+fV/uZ+je1bLQpbPCUu9/ev6u/HhbYGl4VAL/CeQzjOyy6LQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/rhumb-destination": "^7.1.0", + "@turf/transform-rotate": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/envelope": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/envelope/-/envelope-7.1.0.tgz", + "integrity": "sha512-WeLQse9wuxsxhzSqrJA6Ha7rLWnLKgdKY9cfxmJKHSpgqcJyNk60m7+T3UpI/nkGwpfbpeyB3EGC1EWPbxiDUg==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/bbox-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/explode": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/explode/-/explode-7.1.0.tgz", + "integrity": "sha512-To+GUbU6HtcHZ8S0w/dw1EbdQIOCXALTr6Ug5/IFg8hIBMJelDpVr3Smwy8uqhDRFinY2eprBwQnDPcd10eCqA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/flatten": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/flatten/-/flatten-7.1.0.tgz", + "integrity": "sha512-Kb23pqEarcLsdBqnQcK0qTrSMiWNTVb9tOFrNlZc66DIhDLAdpOKG4eqk00CMoUzWTixlnawDgJRqcStRrR4WA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/flip": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/flip/-/flip-7.1.0.tgz", + "integrity": "sha512-vac73W8WblzzNFanzWYLBzWDIcqc5xczOrtEO07RDEiKEI3Heo0471Jed3v9W506uuOX6/HAiCjXbRjTLjiLfw==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/geojson-rbush": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/geojson-rbush/-/geojson-rbush-7.1.0.tgz", + "integrity": "sha512-j1C7Ohlxa1z644bNOpgibcFGaDLgLXGLOzwF1tfQaP5y7E4PJQUXL0DWIgNb3Ke7gZC05LPHM25a5TRReUfFBQ==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/great-circle": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/great-circle/-/great-circle-7.1.0.tgz", + "integrity": "sha512-92q5fqUp5oW+FYekUIrUVR5PZBWbOV6NHKHPIiNahiPvtkpZItbbjoO+tGn5+2i8mxZP9FGOthayJe4V0a1xkg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/helpers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.1.0.tgz", + "integrity": "sha512-dTeILEUVeNbaEeoZUOhxH5auv7WWlOShbx7QSd4s0T4Z0/iz90z9yaVCtZOLbU89umKotwKaJQltBNO9CzVgaQ==", + "dependencies": { + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/hex-grid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/hex-grid/-/hex-grid-7.1.0.tgz", + "integrity": "sha512-I+Apx0smOPkMzaS5HHL44YOxSkSUvrz+wtSIETsDFWWLT2xKNkaaEcYU5MkgSoEfQsj082M7EkOIIpocXlA3kg==", + "dependencies": { + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/intersect": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/interpolate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/interpolate/-/interpolate-7.1.0.tgz", + "integrity": "sha512-VWec1OW9gHZLPS3yYkUXAHKMGQuYO4aqh8WCltT7Ym4efrKqkSOE5T+mBqO68QgcL8nY4kiNa8lxwXd0SfXDSA==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/hex-grid": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/point-grid": "^7.1.0", + "@turf/square-grid": "^7.1.0", + "@turf/triangle-grid": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/intersect": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/intersect/-/intersect-7.1.0.tgz", + "integrity": "sha512-T0VhI6yhptX9EoMsuuBETyqV+edyq31SUC8bfuM6kdJ5WwJ0EvUfQoC+3bhMtCOn60lHawrUuGBgW+vCO8KGMg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "polygon-clipping": "^0.15.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/invariant": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.1.0.tgz", + "integrity": "sha512-OCLNqkItBYIP1nE9lJGuIUatWGtQ4rhBKAyTfFu0z8npVzGEYzvguEeof8/6LkKmTTEHW53tCjoEhSSzdRh08Q==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/isobands": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/isobands/-/isobands-7.1.0.tgz", + "integrity": "sha512-iMLTOP/K5C05AttF4N1WeV+KrY4O5VWW/abO0N86XCWh1OeqmIUgqIBKEmhDzttAqC0UK2YrUfj0lI1Ez1fYZQ==", + "dependencies": { + "@turf/area": "^7.1.0", + "@turf/bbox": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/explode": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "marchingsquares": "^1.3.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/isolines": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/isolines/-/isolines-7.1.0.tgz", + "integrity": "sha512-V6QTHXBT5ZsL3s9ZVBJgHYtz3gCFKqNnQLysNE02LE0fVVqaSao3sFrcpghmdDxf0hBCDK8lZVvyRGO6o32LHQ==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "marchingsquares": "^1.3.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/jsts": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@turf/jsts/-/jsts-2.7.1.tgz", + "integrity": "sha512-+nwOKme/aUprsxnLSfr2LylV6eL6T1Tuln+4Hl92uwZ8FrmjDRCH5Bi1LJNVfWCiYgk8+5K+t2zDphWNTsIFDA==", + "dependencies": { + "jsts": "2.7.1" + } + }, + "node_modules/@turf/kinks": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/kinks/-/kinks-7.1.0.tgz", + "integrity": "sha512-KKLYUsyJPU17fODwA81mhHzFYGQYocdbk9NxDPCcdRHvxzM8t95lptkGx/2k/9rXBs1DK7NmyzI4m7zDO0DK7g==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/length": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/length/-/length-7.1.0.tgz", + "integrity": "sha512-wUJj9WLKEudG1ngNao2ZwD+Dt6UkvWIbubuJ6lR6FndFDL3iezFhNGy0IXS+0xH9kXi2apiTnM9Vk5+i8BTEvQ==", + "dependencies": { + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-arc": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-arc/-/line-arc-7.1.0.tgz", + "integrity": "sha512-9/bM34PozTyJ5FXXPAzl/j0RpcTImgMFJZ0WhH0pZZEZRum6P0rJnENt2E2qI441zeozQ9H6X5DCiJogDmRUEw==", + "dependencies": { + "@turf/circle": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-chunk": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-chunk/-/line-chunk-7.1.0.tgz", + "integrity": "sha512-1lIUfqAQvCWAuUNC2ip8UYmM5kDltXOidLPW45Ee1OAIKYGBeFNtjwnxc0mQ40tnfTXclTYLDdOOP9LShspT9w==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/length": "^7.1.0", + "@turf/line-slice-along": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-intersect": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-intersect/-/line-intersect-7.1.0.tgz", + "integrity": "sha512-JI3dvOsAoCqd4vUJ134FIzgcC42QpC/tBs+b4OJoxWmwDek3REv4qGaZY6wCg9X4hFSlCKFcnhMIQQZ/n720Qg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "sweepline-intersections": "^1.5.0", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-offset": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-offset/-/line-offset-7.1.0.tgz", + "integrity": "sha512-pz6irzhiQlJurU7DoXada6k3ei7PzY+VpsE/Wotm0D2KEAnoxqum2WK0rqqrhKPHKn+xpUGsHN9W/6K+qtmaHg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-overlap": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-overlap/-/line-overlap-7.1.0.tgz", + "integrity": "sha512-BdHuEoFAtqvVw3LkjCdivG035nfuwZuxji2ijst+mkmDnlv7uwSBudJqcDGjU6up2r8P1mXChS4im4xjUz+lwg==", + "dependencies": { + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/geojson-rbush": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-segment": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/nearest-point-on-line": "^7.1.0", + "@types/geojson": "^7946.0.10", + "fast-deep-equal": "^3.1.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-segment": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-segment/-/line-segment-7.1.0.tgz", + "integrity": "sha512-9rgIIH6ZzC3IiWxDQtKsq+j6eu8fRinMkJeusfI9HqOTm4vO02Ll4F/FigjOMOO/6X3TJ+Pqe3gS99TUaBINkw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-slice": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-slice/-/line-slice-7.1.0.tgz", + "integrity": "sha512-44xcjgMQxTa7tTAZlSD3t1cFjHi5SCfAqjg1ONv45EYKsQSonPaxD7LGzCbU5pR2RJjx3R7QRJx2G88hnGcXjQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/nearest-point-on-line": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-slice-along": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-slice-along/-/line-slice-along-7.1.0.tgz", + "integrity": "sha512-UwfnFORZnu4xdnuRXiQM3ODa8f9Q0FBjQF/XHNsPEI/xxmnwgQj3MZiULbAeHUbtU/7psTC7gEjfE3Lf0tcKQw==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-split": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-split/-/line-split-7.1.0.tgz", + "integrity": "sha512-QqUAmtlrnEu75cpLOmpEuiYU63BeVwpSKOBllBbu5gkP+7H/WBM/9fh7J0VgHNFHzqZCKiu8v4158k+CZr0QAg==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/geojson-rbush": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/line-segment": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/nearest-point-on-line": "^7.1.0", + "@turf/square": "^7.1.0", + "@turf/truncate": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/line-to-polygon": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/line-to-polygon/-/line-to-polygon-7.1.0.tgz", + "integrity": "sha512-n/IWBRbo+l4XDTz4sfQsQm5bU9xex8KrthK397jQasd7a9PiOKGon9Z1t/lddTJhND6ajVyJ3hl+eZMtpQaghQ==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/mask": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/mask/-/mask-7.1.0.tgz", + "integrity": "sha512-d+u3IIiRhe17TDfP/+UMn9qRlJYPJpK7sj6WorsssluGi0yIG/Z24uWpcLskWKSI8NNgkIbDrp+GIYkJi2t7SA==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "polygon-clipping": "^0.15.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/meta": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.1.0.tgz", + "integrity": "sha512-ZgGpWWiKz797Fe8lfRj7HKCkGR+nSJ/5aKXMyofCvLSc2PuYJs/qyyifDPWjASQQCzseJ7AlF2Pc/XQ/3XkkuA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/midpoint": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/midpoint/-/midpoint-7.1.0.tgz", + "integrity": "sha512-uiUU9TwRZOCeiTUn8+7oE6MJUvclfq+n6KQ5VCMTZXiRUJjPu7nDLpBle1t2WSv7/w7O0kSQ4FfKXh0gHnkJOw==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/moran-index": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/moran-index/-/moran-index-7.1.0.tgz", + "integrity": "sha512-xsvAr3IRF/C6PlRMoN/ANrRx6c3QFUJgBCIVfI7re+Lkdprrzgw1HZA48ZjP4F91xbhgA1scnRgQdHFi2vO2SA==", + "dependencies": { + "@turf/distance-weight": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-neighbor-analysis": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/nearest-neighbor-analysis/-/nearest-neighbor-analysis-7.1.0.tgz", + "integrity": "sha512-FAhT8/op3DuvqH0XFhv055JhYq/FC4aaIxEZ4hj8c7W6sYhUHAQgdRZ0tJ1RLe5/h+eXhCTbQ+DFfnfv3klu8g==", + "dependencies": { + "@turf/area": "^7.1.0", + "@turf/bbox": "^7.1.0", + "@turf/bbox-polygon": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/nearest-point": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/nearest-point/-/nearest-point-7.1.0.tgz", + "integrity": "sha512-VyInmhqfVWp+jE7sCK95o46qc4tDjAgzbRfRjr+rTgfFS1Sndyy1PdwyNn6TjBFDxiM6e+mjMEeGPjb1smJlEg==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point-on-line": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/nearest-point-on-line/-/nearest-point-on-line-7.1.0.tgz", + "integrity": "sha512-aTjAOm7ab0tl5JoxGYRx/J/IbRL1DY1ZCIYQDMEQjK5gOllhclgeBC0wDXDkEZFGaVftjw0W2RtE2I0jX7RG4A==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/nearest-point-to-line": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/nearest-point-to-line/-/nearest-point-to-line-7.1.0.tgz", + "integrity": "sha512-rY2F/iY4S6U8H0hIoOI25xMWYEiKywxeTvTvn5GP8KCu+2oemfZROWa7n2+hQDRwO2/uaegrGEpxO7zlFarvzg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/point-to-line-distance": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/planepoint": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/planepoint/-/planepoint-7.1.0.tgz", + "integrity": "sha512-hFORBkCd7Q0kNUzLqksT4XglLgTQF9tCjG+dbnZ1VehpZu+w+vlHdoW/mY7XCX3Kj1ObiyzVmXffmVYgwXwF6Q==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-grid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/point-grid/-/point-grid-7.1.0.tgz", + "integrity": "sha512-ihuuUcWuCu4Z1+34UYCM5NGsU2DJaB4uE8cS3jDQoUqlc+8ii2ng8kcGEtTwVn0HdPsoKA7bgvSZcisJO0v6Ww==", + "dependencies": { + "@turf/boolean-within": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-on-feature": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/point-on-feature/-/point-on-feature-7.1.0.tgz", + "integrity": "sha512-lOO5J9I0diuGbN+r6jViEKRH3qfymsBvv25b7U0MuP8g/YC19ncUXZ86dmKfJx1++Rb485DS9h0nFvPmJpaOdg==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/center": "^7.1.0", + "@turf/explode": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/nearest-point": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/point-to-line-distance": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/point-to-line-distance/-/point-to-line-distance-7.1.0.tgz", + "integrity": "sha512-Ps9eTOCaiNgxDaSNQux0wAcSLcrI0y0zYFaD9HnVm+yCMRliQXneFti2XXotS+gR7TpgnLRAAzyx4VzJMSN2tw==", + "dependencies": { + "@turf/bearing": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/projection": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@turf/rhumb-distance": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/points-within-polygon": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/points-within-polygon/-/points-within-polygon-7.1.0.tgz", + "integrity": "sha512-SzqeD9Gcp11rEya+rCVMy6IPuYMrphNEkCiQ39W6ec9hsaqKlruqmtudKhhckMGVLVUUBCQAu5f55yjcDfVW2w==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-smooth": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/polygon-smooth/-/polygon-smooth-7.1.0.tgz", + "integrity": "sha512-mTlmg4XUP5rKgCP/73N91owkAXIc3t1ZKLuwsJGQM1/Op48T3rJmDwVR/WZIMnVlxl5tFbssWCCB3blj4ivx9g==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-tangents": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/polygon-tangents/-/polygon-tangents-7.1.0.tgz", + "integrity": "sha512-ffBgHXtkrpgkNs8E6s9sVLSKG4lPGH3WBk294FNKBt9NS+rbhNCv8yTuOMeP0bOm/WizaCq/SUtVryJpUSoI/g==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/boolean-within": "^7.1.0", + "@turf/explode": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/nearest-point": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygon-to-line": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/polygon-to-line/-/polygon-to-line-7.1.0.tgz", + "integrity": "sha512-FBlfyBWNQZCTVGqlJH7LR2VXmvj8AydxrA8zegqek/5oPGtQDeUgIppKmvmuNClqbglhv59QtCUVaDK4bOuCTA==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/polygonize": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/polygonize/-/polygonize-7.1.0.tgz", + "integrity": "sha512-FBjxnOzO29MbE7MWnMPHHYtOo93cQopT5pXhkuPyoKgcTUCntR1+iVFpl5YFbMkYup0j5Oexjo/pbY38lVSZGw==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/envelope": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/projection": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/projection/-/projection-7.1.0.tgz", + "integrity": "sha512-3wHluMoOvXnTe7dfi0kcluTyLNG5MwGsSsK5OA98vkkLH6a1xvItn8e9GcesuT07oB2km/bgefxYEIvjQG5JCA==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/quadrat-analysis": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/quadrat-analysis/-/quadrat-analysis-7.1.0.tgz", + "integrity": "sha512-4O5h9PyWgpqYXja9O+kzr+qk5MUz0IkJqPtt5oWWX5s4jRcLNqiEUf+zi/GDBQkVV8jH3S5klT5CLrF1fxK3hQ==", + "dependencies": { + "@turf/area": "^7.1.0", + "@turf/bbox": "^7.1.0", + "@turf/bbox-polygon": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/point-grid": "^7.1.0", + "@turf/random": "^7.1.0", + "@turf/square-grid": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/random": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/random/-/random-7.1.0.tgz", + "integrity": "sha512-22mXv8ejDMUWkz8DSMMqdZb0s7a0ISJzXt6T9cHovfT//vsotzkVH+5PDxJQjvmigKMnpaUgobHmQss23tAwEQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rectangle-grid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/rectangle-grid/-/rectangle-grid-7.1.0.tgz", + "integrity": "sha512-4d2AuDj4LfMMJxNHbds5yX1oFR3mIVAB5D7mx6pFB0e+YkQW0mE2dUWhDTFGJZM+n45yqbNQ5hg19bmiXv94ug==", + "dependencies": { + "@turf/boolean-intersects": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rewind": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-7.1.0.tgz", + "integrity": "sha512-zX0KDZpeiH89m1vYLTEJdDL6mFyoAsCxcG0P94mXO7/JXWf0AaxzA9MkNnA/d2QYX0G4ioCMjZ5cD6nXb8SXzw==", + "dependencies": { + "@turf/boolean-clockwise": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-bearing": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/rhumb-bearing/-/rhumb-bearing-7.1.0.tgz", + "integrity": "sha512-ESZt70eOljHVnQMFKIdiu8LIHuQlpZgzh2nqSfV40BrYjsjI/sBKeK+sp2cBWk88nsSDlriPuMTNh4f50Jqpkw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-destination": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/rhumb-destination/-/rhumb-destination-7.1.0.tgz", + "integrity": "sha512-WA2TeO3qrv5ZrzNihtTLLYu8X4kd12WEC6JKElm99XhgLao1/4ao2SJUi43l88HqwbrnNiq4TueGQ6tYpXGU7A==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/rhumb-distance": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/rhumb-distance/-/rhumb-distance-7.1.0.tgz", + "integrity": "sha512-fR1V+yC4E1tnbdThomosiLcv0PQOwbfLSPM8rSWuxbMcJtffsncWxyJ0+N1F5juuHbcdaYhlduX8ri5I0ZCejw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/sample": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/sample/-/sample-7.1.0.tgz", + "integrity": "sha512-9Iq/Ankr4+sgBoh4FpuVVvoW+AA10eej3FS89Zu79SFdCqUIdT7T42Nn3MlSVj4jMyA1oXyT2HIAlNWkwgLw6Q==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/sector": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/sector/-/sector-7.1.0.tgz", + "integrity": "sha512-2FI2rg//eXpa/l+WJtFfvHaf1NJ7ie2MoJ+RH5dKANtrfoof1Ed+y9dXSyuhem2tp/Srq2GhrjaSofFN5/g5vA==", + "dependencies": { + "@turf/circle": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/line-arc": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/shortest-path": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/shortest-path/-/shortest-path-7.1.0.tgz", + "integrity": "sha512-1UmFhS5zHNacLv5rszoFOXq02BGov1oJvjlDatXsSWAd+Z7tqxpDc8D+41edrXy0ZB0Yxsy6WPNagM6hG9PRaA==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/bbox-polygon": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/clean-coords": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/transform-scale": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/simplify": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/simplify/-/simplify-7.1.0.tgz", + "integrity": "sha512-JypymaoiSiFzGHwEoUkK0OPW1KQSnH3hEsEW3UIRS+apzltJ4HdFovYjsfqQgGZJZ+NJ9+dv7h8pgGLYuqcBUQ==", + "dependencies": { + "@turf/clean-coords": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/square": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/square/-/square-7.1.0.tgz", + "integrity": "sha512-ANuA+WXZheGTLW6Veq0i+/B2S4KMhEHAixDv9gQEb9e6FTyqTJVwrqP4CHI3OzA3DZ/ytFf+NTKVofetO/BBQg==", + "dependencies": { + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/square-grid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/square-grid/-/square-grid-7.1.0.tgz", + "integrity": "sha512-JyhsALULVRlkh8htdTi9aXaXFSUv6wRNbeFbqyGJKKlA5eF+AYmyWdI/BlFGQN27xtbtMPeAuLmj+8jaB2omGw==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/rectangle-grid": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/standard-deviational-ellipse": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/standard-deviational-ellipse/-/standard-deviational-ellipse-7.1.0.tgz", + "integrity": "sha512-JqvQFH/witHh+3XgPC1Qk4+3G8w8WQta2NTJjnGinOgFulH+7RD4DcxCT+XXtCHoeq8IvL9VPJRX3ciaW5nSCg==", + "dependencies": { + "@turf/center-mean": "^7.1.0", + "@turf/ellipse": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/points-within-polygon": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/tag": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/tag/-/tag-7.1.0.tgz", + "integrity": "sha512-cD8TC++DnNmdI1B/apTf3nj2zRNY6SoLRliB8K76OB+70Kev8tOf4ZVgAqOd0u+Hpdg/T6l7dO7fyJ6UouE7jA==", + "dependencies": { + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/tesselate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/tesselate/-/tesselate-7.1.0.tgz", + "integrity": "sha512-E/Z94Mx6kUjvQVbEcSuM9MbEo2dkOczRe4ZzjhFlLgJh1dCkfRgwYLH49mb2CcfG/me1arxoCgmtG+qgm7LrCg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "earcut": "^2.2.4", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/tin": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/tin/-/tin-7.1.0.tgz", + "integrity": "sha512-h8Bdm0IYN6OpKHM8lBRWGxkJnZcxL0KYecf8U6pa6DCEYsEXuEExMTvYSD2OmqIsL5ml8P6RjwgyI+dZeE0O9A==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-rotate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/transform-rotate/-/transform-rotate-7.1.0.tgz", + "integrity": "sha512-Vp7VBZ6DqaPV8mkwSycksBFRLqSj3y16zg+uEPSCsXUjbFtw9DOLcyH2F5vMpnC2bOpS9NOB4hebhJRwBwAPWQ==", + "dependencies": { + "@turf/centroid": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@turf/rhumb-destination": "^7.1.0", + "@turf/rhumb-distance": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-scale": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/transform-scale/-/transform-scale-7.1.0.tgz", + "integrity": "sha512-m5fLnh3JqrWSv0sAC8Aieet/fr5IZND8BFaE9LakMidtNaJqOIPOyVmUoklcrGn6eK6MX+66rRPn+5a1pahlLQ==", + "dependencies": { + "@turf/bbox": "^7.1.0", + "@turf/center": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@turf/rhumb-destination": "^7.1.0", + "@turf/rhumb-distance": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/transform-translate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/transform-translate/-/transform-translate-7.1.0.tgz", + "integrity": "sha512-XA6Oh7VqUDrieY9m9/OF4XpBTd8qlfVGi3ObywojCqtHaHKLK3aXwTBZ276i0QKmZqOQA+2jFa9NhgF/TgBDrw==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/rhumb-destination": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/triangle-grid": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/triangle-grid/-/triangle-grid-7.1.0.tgz", + "integrity": "sha512-hrPyRAuX5PKu7txmc/11VPKrlJDR+JGzd+eijupKTspNLR4n2sqZUx8UXqSxZ/1nq06ScTyjIfGQJVzlRS8BTg==", + "dependencies": { + "@turf/distance": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/intersect": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/truncate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/truncate/-/truncate-7.1.0.tgz", + "integrity": "sha512-rrF3AML9PGZw2i5wmt53ESI+Ln9cZyCXgJ7QrEvkT8NbE4OFgmw6p8/1xT8+VEWFSpD4gHz+hmM+5FaFxXvtNg==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/turf": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/turf/-/turf-7.1.0.tgz", + "integrity": "sha512-7NA6tAjbu9oIvIfpRO5AdPrZbFTlUFU02HVA7sLJM9jFeNIZovW09QuDo23uoS2z5l94SXV1GgKKxN5wo7prCw==", + "dependencies": { + "@turf/along": "^7.1.0", + "@turf/angle": "^7.1.0", + "@turf/area": "^7.1.0", + "@turf/bbox": "^7.1.0", + "@turf/bbox-clip": "^7.1.0", + "@turf/bbox-polygon": "^7.1.0", + "@turf/bearing": "^7.1.0", + "@turf/bezier-spline": "^7.1.0", + "@turf/boolean-clockwise": "^7.1.0", + "@turf/boolean-concave": "^7.1.0", + "@turf/boolean-contains": "^7.1.0", + "@turf/boolean-crosses": "^7.1.0", + "@turf/boolean-disjoint": "^7.1.0", + "@turf/boolean-equal": "^7.1.0", + "@turf/boolean-intersects": "^7.1.0", + "@turf/boolean-overlap": "^7.1.0", + "@turf/boolean-parallel": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/boolean-point-on-line": "^7.1.0", + "@turf/boolean-touches": "^7.1.0", + "@turf/boolean-valid": "^7.1.0", + "@turf/boolean-within": "^7.1.0", + "@turf/buffer": "^7.1.0", + "@turf/center": "^7.1.0", + "@turf/center-mean": "^7.1.0", + "@turf/center-median": "^7.1.0", + "@turf/center-of-mass": "^7.1.0", + "@turf/centroid": "^7.1.0", + "@turf/circle": "^7.1.0", + "@turf/clean-coords": "^7.1.0", + "@turf/clone": "^7.1.0", + "@turf/clusters": "^7.1.0", + "@turf/clusters-dbscan": "^7.1.0", + "@turf/clusters-kmeans": "^7.1.0", + "@turf/collect": "^7.1.0", + "@turf/combine": "^7.1.0", + "@turf/concave": "^7.1.0", + "@turf/convex": "^7.1.0", + "@turf/destination": "^7.1.0", + "@turf/difference": "^7.1.0", + "@turf/dissolve": "^7.1.0", + "@turf/distance": "^7.1.0", + "@turf/distance-weight": "^7.1.0", + "@turf/ellipse": "^7.1.0", + "@turf/envelope": "^7.1.0", + "@turf/explode": "^7.1.0", + "@turf/flatten": "^7.1.0", + "@turf/flip": "^7.1.0", + "@turf/geojson-rbush": "^7.1.0", + "@turf/great-circle": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/hex-grid": "^7.1.0", + "@turf/interpolate": "^7.1.0", + "@turf/intersect": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@turf/isobands": "^7.1.0", + "@turf/isolines": "^7.1.0", + "@turf/kinks": "^7.1.0", + "@turf/length": "^7.1.0", + "@turf/line-arc": "^7.1.0", + "@turf/line-chunk": "^7.1.0", + "@turf/line-intersect": "^7.1.0", + "@turf/line-offset": "^7.1.0", + "@turf/line-overlap": "^7.1.0", + "@turf/line-segment": "^7.1.0", + "@turf/line-slice": "^7.1.0", + "@turf/line-slice-along": "^7.1.0", + "@turf/line-split": "^7.1.0", + "@turf/line-to-polygon": "^7.1.0", + "@turf/mask": "^7.1.0", + "@turf/meta": "^7.1.0", + "@turf/midpoint": "^7.1.0", + "@turf/moran-index": "^7.1.0", + "@turf/nearest-neighbor-analysis": "^7.1.0", + "@turf/nearest-point": "^7.1.0", + "@turf/nearest-point-on-line": "^7.1.0", + "@turf/nearest-point-to-line": "^7.1.0", + "@turf/planepoint": "^7.1.0", + "@turf/point-grid": "^7.1.0", + "@turf/point-on-feature": "^7.1.0", + "@turf/point-to-line-distance": "^7.1.0", + "@turf/points-within-polygon": "^7.1.0", + "@turf/polygon-smooth": "^7.1.0", + "@turf/polygon-tangents": "^7.1.0", + "@turf/polygon-to-line": "^7.1.0", + "@turf/polygonize": "^7.1.0", + "@turf/projection": "^7.1.0", + "@turf/quadrat-analysis": "^7.1.0", + "@turf/random": "^7.1.0", + "@turf/rectangle-grid": "^7.1.0", + "@turf/rewind": "^7.1.0", + "@turf/rhumb-bearing": "^7.1.0", + "@turf/rhumb-destination": "^7.1.0", + "@turf/rhumb-distance": "^7.1.0", + "@turf/sample": "^7.1.0", + "@turf/sector": "^7.1.0", + "@turf/shortest-path": "^7.1.0", + "@turf/simplify": "^7.1.0", + "@turf/square": "^7.1.0", + "@turf/square-grid": "^7.1.0", + "@turf/standard-deviational-ellipse": "^7.1.0", + "@turf/tag": "^7.1.0", + "@turf/tesselate": "^7.1.0", + "@turf/tin": "^7.1.0", + "@turf/transform-rotate": "^7.1.0", + "@turf/transform-scale": "^7.1.0", + "@turf/transform-translate": "^7.1.0", + "@turf/triangle-grid": "^7.1.0", + "@turf/truncate": "^7.1.0", + "@turf/union": "^7.1.0", + "@turf/unkink-polygon": "^7.1.0", + "@turf/voronoi": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/union": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/union/-/union-7.1.0.tgz", + "integrity": "sha512-7VI8jONdBg9qmbfNlLQycPr93l5aU9HGMgWI9M6pb4ERuU2+p8KgffCgs2NyMtP2HxPrKSybzj31g7bnbEKofQ==", + "dependencies": { + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "polygon-clipping": "^0.15.3", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/unkink-polygon": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/unkink-polygon/-/unkink-polygon-7.1.0.tgz", + "integrity": "sha512-pqkirni2aLpRA1ELFIuJz+mkjYyJQX8Ar6BflSu1b0ajY/CTrcDxbIv1x8UfvbybLzdJc4Gxzg5mo4cEtSwtaQ==", + "dependencies": { + "@turf/area": "^7.1.0", + "@turf/boolean-point-in-polygon": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/meta": "^7.1.0", + "@types/geojson": "^7946.0.10", + "rbush": "^3.0.1", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@turf/voronoi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/voronoi/-/voronoi-7.1.0.tgz", + "integrity": "sha512-xUvzPDG6GaqEekgxd+pjeMKJXOYJ3eFIqUHbTe/ISKzzv3f2cFGiR2VH7ZGXri8d4ozzCQbUQ27ilHPPLf5+xw==", + "dependencies": { + "@turf/clone": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@turf/invariant": "^7.1.0", + "@types/d3-voronoi": "^1.1.12", + "@types/geojson": "^7946.0.10", + "d3-voronoi": "1.1.2", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, + "node_modules/@tweenjs/tween.js": { + "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==" + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" + }, + "node_modules/@types/d3-voronoi": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@types/d3-voronoi/-/d3-voronoi-1.1.12.tgz", + "integrity": "sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw==" + }, + "node_modules/@types/debounce": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/debounce/-/debounce-1.2.4.tgz", + "integrity": "sha512-jBqiORIzKDOToaF63Fm//haOCHuwQuLa2202RK4MozpA6lh93eCBc+/8+wZn5OzjJt3ySdc+74SXWXB55Ewtyw==" + }, + "node_modules/@types/draco3d": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz", + "integrity": "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==" + }, + "node_modules/@types/eslint": { + "version": "8.56.12", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz", + "integrity": "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "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/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", + "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.15", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", + "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "27.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", + "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", + "dependencies": { + "jest-matcher-utils": "^27.0.0", + "pretty-format": "^27.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "node_modules/@types/node": { + "version": "22.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.3.tgz", + "integrity": "sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/offscreencanvas": { + "version": "2019.7.3", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz", + "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==" + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" + }, + "node_modules/@types/q": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.8.tgz", + "integrity": "sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==" + }, + "node_modules/@types/qs": { + "version": "6.9.17", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", + "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "node_modules/@types/react": { + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-reconciler": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.26.7.tgz", + "integrity": "sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/readable-stream": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.18.tgz", + "integrity": "sha512-21jK/1j+Wg+7jVw1xnSwy/2Q1VgVjWuFssbYGTREPUBeZ+rqVFl2udq0IkxzPC0ZhOzVceUbyIACFZKLqKEBlA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/@types/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "dev": true + }, + "node_modules/@types/sizzle": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.9.tgz", + "integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==", + "dev": true + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" + }, + "node_modules/@types/stats.js": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz", + "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==" + }, + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.9", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", + "integrity": "sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==", + "dependencies": { + "@types/jest": "*" + } + }, + "node_modules/@types/three": { + "version": "0.169.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.169.0.tgz", + "integrity": "sha512-oan7qCgJBt03wIaK+4xPWclYRPG9wzcg7Z2f5T8xYTNEF95kh0t0lklxLLYBDo7gQiGLYzE6iF4ta7nXF2bcsw==", + "dependencies": { + "@tweenjs/tween.js": "~23.1.3", + "@types/stats.js": "*", + "@types/webxr": "*", + "@webgpu/types": "*", + "fflate": "~0.8.2", + "meshoptimizer": "~0.18.1" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" + }, + "node_modules/@types/webxr": { + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.20.tgz", + "integrity": "sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==" + }, + "node_modules/@types/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "dependencies": { + "@typescript-eslint/utils": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/@use-gesture/core": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz", + "integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==" + }, + "node_modules/@use-gesture/react": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz", + "integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==", + "dependencies": { + "@use-gesture/core": "10.3.1" + }, + "peerDependencies": { + "react": ">= 16.8.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webgpu/types": { + "version": "0.1.51", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.51.tgz", + "integrity": "sha512-ktR3u64NPjwIViNCck+z9QeyN0iPkQCUOQ07ZCV1RzlkfP+olLTeEZ95O1QHS+v4w9vJeY9xj/uJuSphsHy5rQ==" + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.9.tgz", + "integrity": "sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "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==" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.reduce": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.7.tgz", + "integrity": "sha512-mzmiUCVwtiD4lgxYP8g7IYy8El8p2CSMePvIbTS7gchKir/L1fgJrk0yDKmAX6mnRQFKNADYIk8nNlTris5H1Q==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-array-method-boxes-properly": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/attr-accept": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz", + "integrity": "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "dev": true + }, + "node_modules/axe-core": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-loader": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", + "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.4", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-named-asset-import": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", + "peerDependencies": { + "@babel/core": "^7.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", + "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.3", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", + "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-react-app": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", + "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-decorators": "^7.16.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-transform-flow-strip-types": "^7.16.0", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.4", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.3", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bfj": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz", + "integrity": "sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==", + "dependencies": { + "bluebird": "^3.7.2", + "check-types": "^11.2.3", + "hoopy": "^0.1.4", + "jsonpath": "^1.1.1", + "tryer": "^1.0.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.1.0.tgz", + "integrity": "sha512-ClDyJGQkc8ZtzdAAbAwBmhMSpwN/sC9HA8jxdYm6nVUbCfZbe2mgza4qh7AuEYyEPB/c4Kznf9s66bnsKMQDjw==", + "license": "MIT", + "dependencies": { + "@types/readable-stream": "^4.0.0", + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^4.2.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bonjour-service": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "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.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + }, + "node_modules/browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cachedir": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-css": { + "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==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/camera-controls": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-2.9.0.tgz", + "integrity": "sha512-TpCujnP0vqPppTXXJRYpvIy0xq9Tro6jQf2iYUxlDpPCNxkvE/XGaTuwIxnhINOkVP/ob2CRYXtY3iVYXeMEzA==", + "peerDependencies": { + "three": ">=0.126.1" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001683", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001683.tgz", + "integrity": "sha512-iqmNnThZ0n70mNwvxpEC2nBJ037ZHZUoBI5Gorh1Mw6IlEAZujEoU1tXA628iZfzm7R9FvFzxbfdgml82a3k8Q==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/chart.js": { + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz", + "integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==", + "license": "MIT", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/check-types": { + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", + "integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", + "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==" + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dependencies": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/coa/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/coa/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/coa/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "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==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/commist": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz", + "integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==", + "license": "MIT" + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", + "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.0.2", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concaveman": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/concaveman/-/concaveman-1.2.1.tgz", + "integrity": "sha512-PwZYKaM/ckQSa8peP5JpVr7IMJ4Nn/MHIaWUjP4be+KoZ7Botgs8seAZGpmaOM+UZXawcdYRao/px9ycrCihHw==", + "dependencies": { + "point-in-polygon": "^1.1.0", + "rbush": "^3.0.1", + "robust-predicates": "^2.0.4", + "tinyqueue": "^2.0.3" + } + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/core-js": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz", + "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", + "dependencies": { + "browserslist": "^4.24.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.39.0.tgz", + "integrity": "sha512-7fEcWwKI4rJinnK+wLTezeg2smbFFdSBP6E2kQZNbnzM2s1rpKQ6aaRteZSSg7FLU3P0HGGVo/gbpfanU36urg==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "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", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-blank-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-has-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", + "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", + "dependencies": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "postcss": "^8.3.5", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "bin": { + "css-prefers-color-scheme": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + }, + "node_modules/css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dependencies": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" + }, + "node_modules/cssdb": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.11.2.tgz", + "integrity": "sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ] + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "dependencies": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/csso/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + }, + "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/cypress": { + "version": "13.16.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.16.0.tgz", + "integrity": "sha512-g6XcwqnvzXrqiBQR/5gN+QsyRmKRhls1y5E42fyOvsmU7JuY+wM6uHJWj4ZPttjabzbnRvxcik2WemR8+xT6FA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@cypress/request": "^3.0.6", + "@cypress/xvfb": "^1.2.4", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.7.1", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "ci-info": "^4.0.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "process": "^0.11.10", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.5.3", + "supports-color": "^8.1.1", + "tmp": "~0.2.3", + "tree-kill": "1.2.2", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" + }, + "engines": { + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + } + }, + "node_modules/cypress/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/cypress/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + }, + "node_modules/d3-geo": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.7.1.tgz", + "integrity": "sha512-O4AempWAr+P5qbk2bC2FuN/sDW4z+dN2wDf9QV3bxQt4M5HfOEeXLgJ/UKQW0+o1Dj8BE+L5kiDbdWUMjsmQpw==", + "dependencies": { + "d3-array": "1" + } + }, + "node_modules/d3-voronoi": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz", + "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "dev": true + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "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==" + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/default-gateway/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-gateway/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-gpu": { + "version": "5.0.57", + "resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.57.tgz", + "integrity": "sha512-iHfsCCAyxYTE0S4ULs52/DhV2W4l+VT9sTnnYLMwgdNlXKks6PSZleZRDmTCLvPXS4Lt30JI/M5QjhUPwwnZfQ==", + "dependencies": { + "webgl-constants": "^1.1.1" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "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/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "deprecated": "Use your platform's native DOMException instead", + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, + "node_modules/draco3d": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz", + "integrity": "sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==" + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "node_modules/earcut": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.64", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.64.tgz", + "integrity": "sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==" + }, + "node_modules/emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "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==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io-client": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz", + "integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "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/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.23.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz", + "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "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==" + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-react-app": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", + "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@rushstack/eslint-patch": "^1.1.0", + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "babel-preset-react-app": "^10.0.1", + "confusing-browser-globals": "^1.0.11", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^25.3.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-testing-library": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "dependencies": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@babel/plugin-syntax-flow": "^7.14.5", + "@babel/plugin-transform-react-jsx": "^7.14.9", + "eslint": "^8.1.0" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.1.0", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-testing-library": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.1.tgz", + "integrity": "sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==", + "dependencies": { + "@typescript-eslint/utils": "^5.58.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6" + }, + "peerDependencies": { + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", + "dependencies": { + "@types/eslint": "^7.29.0 || ^8.4.1", + "jest-worker": "^28.0.2", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "dev": true + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fast-unique-numbers": { + "version": "8.0.13", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz", + "integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.1.0" + } + }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==" + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/file-selector": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.5.0.tgz", + "integrity": "sha512-s8KNnmIDTBoD0p9uJ9uD0XY38SCeBOtj0UMXyQSLg1Ypfrfj8+dAvwsLjYQkQ2GjhVtp2HrnF5cJzMhBjfD8HA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/geojson-equality-ts": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/geojson-equality-ts/-/geojson-equality-ts-1.0.2.tgz", + "integrity": "sha512-h3Ryq+0mCSN/7yLs0eDgrZhvc9af23o/QuC4aTiuuzP/MRCtd6mf5rLsLRY44jX0RPUfM8c4GqERQmlUxPGPoQ==", + "dependencies": { + "@types/geojson": "^7946.0.14" + } + }, + "node_modules/geojson-polygon-self-intersections": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/geojson-polygon-self-intersections/-/geojson-polygon-self-intersections-1.2.1.tgz", + "integrity": "sha512-/QM1b5u2d172qQVO//9CGRa49jEmclKEsYOQmWP9ooEjj63tBM51m2805xsbxkzlEELQ2REgTf700gUhhlegxA==", + "dependencies": { + "rbush": "^2.0.1" + } + }, + "node_modules/geojson-polygon-self-intersections/node_modules/quickselect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz", + "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ==" + }, + "node_modules/geojson-polygon-self-intersections/node_modules/rbush": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-2.0.2.tgz", + "integrity": "sha512-XBOuALcTm+O/H8G90b6pzu6nX6v2zCKiFG4BJho8a+bY6AER6t8uQUZdi5bomQc0AprCWhEGa7ncAbbRap0bRA==", + "dependencies": { + "quickselect": "^1.0.1" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, + "dependencies": { + "async": "^3.2.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glsl-noise": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/glsl-noise/-/glsl-noise-0.0.0.tgz", + "integrity": "sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "node_modules/gsap": { + "version": "3.12.5", + "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.12.5.tgz", + "integrity": "sha512-srBfnk4n+Oe/ZnMIOXt3gT605BX9x5+rh/prT2F1SsNJsU1XuMiP0E2aptW481OnonOGACZWBqseH5Z7csHxhQ==" + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "node_modules/harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "license": "MIT" + }, + "node_modules/hls.js": { + "version": "1.5.17", + "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.5.17.tgz", + "integrity": "sha512-wA66nnYFvQa1o4DO/BFgLNRKnBTVXpNeldGRBJ2Y0SvFtdwvFKCbqa9zhHoZLoxHhZ+jYsj3aIBkWQQCPNOhMw==" + }, + "node_modules/hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", + "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-signature": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", + "integrity": "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.18.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "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==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, + "node_modules/identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "dependencies": { + "harmony-reflect": "^1.4.6" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immutable": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", + "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==" + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/its-fine": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.2.5.tgz", + "integrity": "sha512-fXtDA0X0t0eBYAGLVM5YsgJGsJ5jEmqZEPrGbzdf5awjv0xE7nqv3TVnvtUF060Tkes15DbDAKW/I48vsb6SyA==", + "dependencies": { + "@types/react-reconciler": "^0.28.0" + }, + "peerDependencies": { + "react": ">=18.0" + } + }, + "node_modules/its-fine/node_modules/@types/react-reconciler": { + "version": "0.28.8", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz", + "integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dependencies": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/jest-changed-files/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dependencies": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dependencies": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-config/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dependencies": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dependencies": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-util/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", + "dependencies": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "jest": "^27.0.0 || ^28.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/console/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dependencies": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-watch-typeahead/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "dependencies": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/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==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/jest-watch-typeahead/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "dependencies": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.2.tgz", + "integrity": "sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg==", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/form-data": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.2.tgz", + "integrity": "sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/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==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsdom/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==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpath": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", + "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", + "dependencies": { + "esprima": "1.2.2", + "static-eval": "2.0.2", + "underscore": "1.12.1" + } + }, + "node_modules/jsonpath/node_modules/esprima": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", + "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "node_modules/jsts": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/jsts/-/jsts-2.7.1.tgz", + "integrity": "sha512-x2wSZHEBK20CY+Wy+BPE7MrFQHW6sIsdaGUMEqmGAio+3gFzQaBYPwLRonUfQf9Ak8pBieqj9tUofX1+WtAEIg==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/launch-editor": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", + "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "dev": true, + "engines": { + "node": "> 0.8" + } + }, + "node_modules/leva": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/leva/-/leva-0.10.0.tgz", + "integrity": "sha512-RiNJWmeqQdKIeHuVXgshmxIHu144a2AMYtLxKf8Nm1j93pisDPexuQDHKNdQlbo37wdyDQibLjY9JKGIiD7gaw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-portal": "1.0.2", + "@radix-ui/react-tooltip": "1.0.5", + "@stitches/react": "^1.2.8", + "@use-gesture/react": "^10.2.5", + "colord": "^2.9.2", + "dequal": "^2.0.2", + "merge-value": "^1.0.0", + "react-colorful": "^5.5.1", + "react-dropzone": "^12.0.0", + "v8n": "^1.3.3", + "zustand": "^3.6.9" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/leva/node_modules/zustand": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", + "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", + "license": "MIT", + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "engines": { + "node": ">=10" + } + }, + "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==" + }, + "node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "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", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/maath": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/maath/-/maath-0.10.8.tgz", + "integrity": "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g==", + "peerDependencies": { + "@types/three": ">=0.134.0", + "three": ">=0.134.0" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marchingsquares": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/marchingsquares/-/marchingsquares-1.3.3.tgz", + "integrity": "sha512-gz6nNQoVK7Lkh2pZulrT4qd4347S/toG9RXH2pyzhLgkL5mLkBoqgv4EvAGXcV0ikDW72n/OQb3Xe8bGagQZCg==" + }, + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/merge-value/-/merge-value-1.0.0.tgz", + "integrity": "sha512-fJMmvat4NeKz63Uv9iHWcPDjCWcCkoiRoajRTEO8hlhUC6rwaHg0QCF9hBOTjZmm4JuglPckPSTtcuJL5kp0TQ==", + "license": "MIT", + "dependencies": { + "get-value": "^2.0.6", + "is-extendable": "^1.0.0", + "mixin-deep": "^1.2.0", + "set-value": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/meshline": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/meshline/-/meshline-3.3.1.tgz", + "integrity": "sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ==", + "peerDependencies": { + "three": ">=0.137" + } + }, + "node_modules/meshoptimizer": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", + "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "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==", + "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", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", + "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "license": "MIT", + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mqtt": { + "version": "5.10.4", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.10.4.tgz", + "integrity": "sha512-wN+SuhT2/ZaG6NPxca0N6YtRivnMxk6VflxQUEeqDH4erKdj+wPAGhHmcTLzvqfE4sJRxrEJ+XJxUc0No0E7eQ==", + "license": "MIT", + "dependencies": { + "@types/readable-stream": "^4.0.18", + "@types/ws": "^8.5.14", + "commist": "^3.2.0", + "concat-stream": "^2.0.0", + "debug": "^4.4.0", + "help-me": "^5.0.0", + "lru-cache": "^10.4.3", + "minimist": "^1.2.8", + "mqtt-packet": "^9.0.1", + "number-allocator": "^1.0.14", + "readable-stream": "^4.7.0", + "reinterval": "^1.1.0", + "rfdc": "^1.4.1", + "split2": "^4.2.0", + "worker-timers": "^7.1.8", + "ws": "^8.18.0" + }, + "bin": { + "mqtt": "build/bin/mqtt.js", + "mqtt_pub": "build/bin/pub.js", + "mqtt_sub": "build/bin/sub.js" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.2.tgz", + "integrity": "sha512-MvIY0B8/qjq7bKxdN1eD+nrljoeaai+qjLJgfRn3TiMuz0pamsIWY2bFODPZMSNmabsLANXsLl4EMoWvlaTZWA==", + "license": "MIT", + "dependencies": { + "bl": "^6.0.8", + "debug": "^4.3.4", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/mqtt/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mqtt/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/mqtt/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/mqtt/node_modules/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "license": "MIT", + "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/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/n8ao": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/n8ao/-/n8ao-1.9.3.tgz", + "integrity": "sha512-OZX+u8LaEfxLi6lupuyT8gIv80D6D8FIeKbBNkCyY0nE+1wmm6sQ4yeyW3a15lFMrfTcEhe0AU8QhhDejHg7sg==", + "peerDependencies": { + "postprocessing": ">=6.30.0", + "three": ">=0.137" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "optional": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/nwsapi": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==" + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.8.tgz", + "integrity": "sha512-qkHIGe4q0lSYMv0XI4SsBTJz3WaURhLvd0lKSgtVuOsJ2krg4SgMw3PIRQFMp07yi++UR3se2mkcLqsBNpBb/A==", + "dependencies": { + "array.prototype.reduce": "^1.0.6", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "gopd": "^1.0.1", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", + "dev": true + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/picocolors": { + "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", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/point-in-polygon": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/point-in-polygon/-/point-in-polygon-1.1.0.tgz", + "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw==" + }, + "node_modules/point-in-polygon-hao": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.1.0.tgz", + "integrity": "sha512-3hTIM2j/v9Lio+wOyur3kckD4NxruZhpowUbEgmyikW+a2Kppjtu1eN+AhnMQtoHW46zld88JiYWv6fxpsDrTQ==" + }, + "node_modules/polygon-clipping": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/polygon-clipping/-/polygon-clipping-0.15.7.tgz", + "integrity": "sha512-nhfdr83ECBg6xtqOAJab1tbksbBAOMUltN60bU+llHVOL0e5Onm1WpAXXWXVB39L8AJFssoIhEVuy/S90MmotA==", + "dependencies": { + "robust-predicates": "^3.0.2", + "splaytree": "^3.1.0" + } + }, + "node_modules/polygon-clipping/node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-browser-comments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "browserslist": ">=4", + "postcss": ">=8" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-custom-properties": { + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", + "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-flexbugs-fixes": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", + "peerDependencies": { + "postcss": "^8.1.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-load-config/node_modules/yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.1.0.tgz", + "integrity": "sha512-rm0bdSv4jC3BDma3s9H19ZddW0aHX6EoqwDYU2IfZhRN+53QrufTRo2IdkAbRqLx4R2IYbZnbjKKxg4VN5oU9Q==", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "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.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nesting": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", + "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-normalize": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", + "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", + "dependencies": { + "@csstools/normalize.css": "*", + "postcss-browser-comments": "^4", + "sanitize.css": "*" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "browserslist": ">= 4", + "postcss": ">= 8" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-preset-env": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", + "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", + "dependencies": { + "@csstools/postcss-cascade-layers": "^1.1.1", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", + "@csstools/postcss-progressive-custom-properties": "^1.3.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.13", + "browserslist": "^4.21.4", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.1.0", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.10", + "postcss-custom-selectors": "^6.0.3", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", + "postcss-env-function": "^4.0.6", + "postcss-focus-visible": "^6.0.4", + "postcss-focus-within": "^5.0.4", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.2.0", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-selector-parser": { + "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" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/postcss-svgo/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/postcss-svgo/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/postcss-svgo/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-svgo/node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "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==" + }, + "node_modules/postprocessing": { + "version": "6.36.4", + "resolved": "https://registry.npmjs.org/postprocessing/-/postprocessing-6.36.4.tgz", + "integrity": "sha512-3fAyBGuLNR7Rg/q+f2SNlsVCI5mDrymvxhOif3tPKEej8M38z4TvwzNZm+RNpRY2tACE7qQUNE5IHyMcqgvlAg==", + "peerDependencies": { + "three": ">= 0.157.0 < 0.171.0" + } + }, + "node_modules/potpack": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz", + "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/promise-worker-transferable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz", + "integrity": "sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw==", + "dependencies": { + "is-promise": "^2.1.0", + "lie": "^3.0.2" + } + }, + "node_modules/prompt-sync": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/prompt-sync/-/prompt-sync-4.2.0.tgz", + "integrity": "sha512-BuEzzc5zptP5LsgV5MZETjDaKSWfchl5U9Luiu8SKp7iZWD5tZalOxvNcZRwv+d2phNFr8xlbxmFNcRKfJOzJw==", + "dependencies": { + "strip-ansi": "^5.0.0" + } + }, + "node_modules/prompt-sync/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/prompt-sync/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "dev": true + }, + "node_modules/psl": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.13.0.tgz", + "integrity": "sha512-BFwmFXiJoFqlUpZ5Qssolv15DMyc84gTBds1BjsV1BfXEo1UyyD7GsmN67n7J77uRhoSNW1AXtXKPLcBFQn9Aw==", + "dependencies": { + "punycode": "^2.3.1" + } + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quickselect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "dependencies": { + "performance-now": "^2.1.0" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rbush": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz", + "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", + "dependencies": { + "quickselect": "^2.0.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-app-polyfill": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", + "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", + "dependencies": { + "core-js": "^3.19.2", + "object-assign": "^4.1.1", + "promise": "^8.1.0", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.9", + "whatwg-fetch": "^3.6.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-app-polyfill/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/react-chartjs-2": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz", + "integrity": "sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==", + "license": "MIT", + "peerDependencies": { + "chart.js": "^4.1.1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-composer": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/react-composer/-/react-composer-5.0.3.tgz", + "integrity": "sha512-1uWd07EME6XZvMfapwZmc7NgCZqDemcvicRi3wMJzXsQLvZ3L7fTHVyPy1bZdnWXM4iPjYuNE+uJ41MLKeTtnA==", + "dependencies": { + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/react-dev-utils/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-dom/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/react-dropzone": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-12.1.0.tgz", + "integrity": "sha512-iBYHA1rbopIvtzokEX4QubO6qk5IF/x3BtKGu74rF2JkQDXnwC4uO/lHKpaw4PJIV6iIAYOlwLv2FpiGyqHNog==", + "license": "MIT", + "dependencies": { + "attr-accept": "^2.2.2", + "file-selector": "^0.5.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "react": ">= 16.8" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/react-reconciler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.27.0.tgz", + "integrity": "sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.21.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/react-refresh": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", + "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.4.0.tgz", + "integrity": "sha512-Y2g5ObjkvX3VFeVt+0CIPuYd9PpgqCslG7ASSIdN73LwA1nNWzcMLaoMRJfP3prZFI92svxFwbn7XkLJ+UPQ6A==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.4.0.tgz", + "integrity": "sha512-VlksBPf3n2bijPvnA7nkTsXxMAKOj+bWp4R9c3i+bnwlSOFAGOkJkKhzy/OsRkWaBMICqcAl1JDzh9ZSOze9CA==", + "license": "MIT", + "dependencies": { + "react-router": "7.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/react-scripts": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", + "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", + "dependencies": { + "@babel/core": "^7.16.0", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", + "@svgr/webpack": "^5.5.0", + "babel-jest": "^27.4.2", + "babel-loader": "^8.2.3", + "babel-plugin-named-asset-import": "^0.3.8", + "babel-preset-react-app": "^10.0.1", + "bfj": "^7.0.2", + "browserslist": "^4.18.1", + "camelcase": "^6.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "css-loader": "^6.5.1", + "css-minimizer-webpack-plugin": "^3.2.0", + "dotenv": "^10.0.0", + "dotenv-expand": "^5.1.0", + "eslint": "^8.3.0", + "eslint-config-react-app": "^7.0.1", + "eslint-webpack-plugin": "^3.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.0", + "html-webpack-plugin": "^5.5.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.4.3", + "jest-resolve": "^27.4.2", + "jest-watch-typeahead": "^1.0.0", + "mini-css-extract-plugin": "^2.4.5", + "postcss": "^8.4.4", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader": "^6.2.1", + "postcss-normalize": "^10.0.1", + "postcss-preset-env": "^7.0.1", + "prompts": "^2.4.2", + "react-app-polyfill": "^3.0.0", + "react-dev-utils": "^12.0.1", + "react-refresh": "^0.11.0", + "resolve": "^1.20.0", + "resolve-url-loader": "^4.0.0", + "sass-loader": "^12.3.0", + "semver": "^7.3.5", + "source-map-loader": "^3.0.0", + "style-loader": "^3.3.1", + "tailwindcss": "^3.0.2", + "terser-webpack-plugin": "^5.2.5", + "webpack": "^5.64.4", + "webpack-dev-server": "^4.6.0", + "webpack-manifest-plugin": "^4.0.2", + "workbox-webpack-plugin": "^6.4.1" + }, + "bin": { + "react-scripts": "bin/react-scripts.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + }, + "peerDependencies": { + "react": ">= 16", + "typescript": "^3.2.1 || ^4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/react-scripts/node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "engines": { + "node": ">=10" + } + }, + "node_modules/react-scripts/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/react-toastify": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.6.tgz", + "integrity": "sha512-yYjp+omCDf9lhZcrZHKbSq7YMuK0zcYkDFTzfRFgTXkTFHZ1ToxwAonzA4JI5CxA91JpjFLmwEsZEgfYfOqI1A==", + "dependencies": { + "clsx": "^2.1.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "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==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/recursive-readdir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/recursive-readdir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", + "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.12.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==" + }, + "node_modules/regjsparser": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==", + "license": "MIT" + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dev": true, + "dependencies": { + "throttleit": "^1.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "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==" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=8.9" + }, + "peerDependencies": { + "rework": "1.0.1", + "rework-visit": "1.0.0" + }, + "peerDependenciesMeta": { + "rework": { + "optional": true + }, + "rework-visit": { + "optional": true + } + } + }, + "node_modules/resolve-url-loader/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/resolve-url-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/resolve-url-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve.exports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/robust-predicates": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-2.0.4.tgz", + "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==" + }, + "node_modules/rollup": { + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==" + }, + "node_modules/sanitize.css": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", + "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" + }, + "node_modules/sass": { + "version": "1.81.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.81.0.tgz", + "integrity": "sha512-Q4fOxRfhmv3sqCLoGfvrC9pRV8btc0UtqL9mN6Yrv6Qi9ScL55CVH1vlPP863ISLEEMNLLuu9P+enCeGHlnzhA==", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass-loader": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", + "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/sass/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/scheduler": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz", + "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/skmeans": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz", + "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "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" + } + }, + "node_modules/source-map-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", + "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", + "dependencies": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/splaytree": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/splaytree/-/splaytree-3.1.2.tgz", + "integrity": "sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A==" + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "license": "MIT", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "license": "MIT", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, + "node_modules/static-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", + "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "dependencies": { + "escodegen": "^1.8.1" + } + }, + "node_modules/static-eval/node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-eval/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/static-eval/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-eval/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/stats-gl": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-2.4.2.tgz", + "integrity": "sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ==", + "dependencies": { + "@types/three": "*", + "three": "^0.170.0" + }, + "peerDependencies": { + "@types/three": "*", + "three": "*" + } + }, + "node_modules/stats-gl/node_modules/three": { + "version": "0.170.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.170.0.tgz", + "integrity": "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==" + }, + "node_modules/stats.js": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz", + "integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" + }, + "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==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "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==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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==" + }, + "node_modules/string-width/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==" + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "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==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/sucrase/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/suspend-react": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz", + "integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==", + "peerDependencies": { + "react": ">=17.0" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "dependencies": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/svgo/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/svgo/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/svgo/node_modules/css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "node_modules/svgo/node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/svgo/node_modules/domutils/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/svgo/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/svgo/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sweepline-intersections": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sweepline-intersections/-/sweepline-intersections-1.5.0.tgz", + "integrity": "sha512-AoVmx72QHpKtItPu72TzFL+kcYjd67BPLDoR0LarIk+xyaRg+pDTMFXndIEvZf9xEKnJv6JdhgRMnocoG0D3AQ==", + "dependencies": { + "tinyqueue": "^2.0.0" + } + }, + "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==" + }, + "node_modules/tailwindcss": { + "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.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "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", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dependencies": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "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==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/three": { + "version": "0.168.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.168.0.tgz", + "integrity": "sha512-6m6jXtDwMJEK/GGMbAOTSAmxNdzKvvBzgd7q8bE/7Tr6m7PaBh5kKLrN7faWtlglXbzj7sVba48Idwx+NRsZXw==" + }, + "node_modules/three-bvh-csg": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/three-bvh-csg/-/three-bvh-csg-0.0.16.tgz", + "integrity": "sha512-RgC5dY0hAKdfd1bmD3o2CDfmK9GTkvsA1ECzoqTMhSkjSc2zp1z4Wpa5+emLi/EosF5P6+aK2veTxTLZA9+Mhw==", + "peerDependencies": { + "three": ">=0.151.0", + "three-mesh-bvh": ">=0.6.6" + } + }, + "node_modules/three-mesh-bvh": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.6.8.tgz", + "integrity": "sha512-EGebF9DZx1S8+7OZYNNTT80GXJZVf+UYXD/HyTg/e2kR/ApofIFfUS4ZzIHNnUVIadpnLSzM4n96wX+l7GMbnQ==", + "peerDependencies": { + "three": ">= 0.151.0" + } + }, + "node_modules/three-stdlib": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.34.0.tgz", + "integrity": "sha512-U5qJYWgUKBFJqr1coMSbczA964uvouzBjQbtJlaI9LfMwy7hr+kc1Mfh0gqi/2872KmGu9utgff6lj8Oti8+VQ==", + "dependencies": { + "@types/draco3d": "^1.4.0", + "@types/offscreencanvas": "^2019.6.4", + "@types/webxr": "^0.5.2", + "draco3d": "^1.4.1", + "fflate": "^0.6.9", + "potpack": "^1.0.1" + }, + "peerDependencies": { + "three": ">=0.128.0" + } + }, + "node_modules/three-stdlib/node_modules/fflate": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz", + "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==" + }, + "node_modules/throat": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" + }, + "node_modules/throttleit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "node_modules/tinyqueue": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==" + }, + "node_modules/tldts": { + "version": "6.1.63", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.63.tgz", + "integrity": "sha512-YWwhsjyn9sB/1rOkSRYxvkN/wl5LFM1QDv6F2pVR+pb/jFne4EOBxHfkKVWvDIBEAw9iGOwwubHtQTm0WRT5sQ==", + "dev": true, + "dependencies": { + "tldts-core": "^6.1.63" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.63", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.63.tgz", + "integrity": "sha512-H1XCt54xY+QPbwhTgmxLkepX0MVHu3USfMmejiCOdkMbRcP22Pn2FVF127r/GWXVDmXTRezyF3Ckvhn4Fs6j7Q==", + "dev": true + }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/topojson-client": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", + "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", + "dependencies": { + "commander": "2" + }, + "bin": { + "topo2geo": "bin/topo2geo", + "topomerge": "bin/topomerge", + "topoquantize": "bin/topoquantize" + } + }, + "node_modules/topojson-client/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/topojson-server": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/topojson-server/-/topojson-server-3.0.1.tgz", + "integrity": "sha512-/VS9j/ffKr2XAOjlZ9CgyyeLmgJ9dMwq6Y0YEON8O7p/tGGk+dCWnrE03zEdu7i4L7YsFZLEPZPzCvcB7lEEXw==", + "dependencies": { + "commander": "2" + }, + "bin": { + "geo2topo": "bin/geo2topo" + } + }, + "node_modules/topojson-server/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/tough-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "dev": true, + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/troika-three-text": { + "version": "0.52.2", + "resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.52.2.tgz", + "integrity": "sha512-UGYwjKnR8RgmyOIpo0/KiSW0wySQ155BQXNLoSWA1liKzXG+RyHM+dvTIDawHGVQcqjqyunFlVY32xm/HDqjpw==", + "dependencies": { + "bidi-js": "^1.0.2", + "troika-three-utils": "^0.52.0", + "troika-worker-utils": "^0.52.0", + "webgl-sdf-generator": "1.1.1" + }, + "peerDependencies": { + "three": ">=0.125.0" + } + }, + "node_modules/troika-three-utils": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/troika-three-utils/-/troika-three-utils-0.52.0.tgz", + "integrity": "sha512-00oxqIIehtEKInOTQekgyknBuRUj1POfOUE2q1OmL+Xlpp4gIu+S0oA0schTyXsDS4d9DkR04iqCdD40rF5R6w==", + "peerDependencies": { + "three": ">=0.125.0" + } + }, + "node_modules/troika-worker-utils": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/troika-worker-utils/-/troika-worker-utils-0.52.0.tgz", + "integrity": "sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw==" + }, + "node_modules/tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + }, + "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==" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tunnel-rat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tunnel-rat/-/tunnel-rat-0.1.2.tgz", + "integrity": "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==", + "dependencies": { + "zustand": "^4.3.2" + } + }, + "node_modules/tunnel-rat/node_modules/zustand": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz", + "integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==", + "dependencies": { + "use-sync-external-store": "1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", + "license": "ISC" + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", + "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "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==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz", + "integrity": "sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/v8n": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/v8n/-/v8n-1.5.1.tgz", + "integrity": "sha512-LdabyT4OffkyXFCe9UT+uMkxNBs5rcTVuZClvxQr08D5TUgo1OFKkoT65qYRCsiKBl/usHjpXvP4hHMzzDRj3A==", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-vitals": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-2.1.4.tgz", + "integrity": "sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg==" + }, + "node_modules/webgl-constants": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/webgl-constants/-/webgl-constants-1.1.1.tgz", + "integrity": "sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg==" + }, + "node_modules/webgl-sdf-generator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz", + "integrity": "sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==" + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/webpack": { + "version": "5.96.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", + "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "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/webpack-manifest-plugin": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", + "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", + "dependencies": { + "tapable": "^2.0.0", + "webpack-sources": "^2.2.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "peerDependencies": { + "webpack": "^4.44.2 || ^5.47.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dependencies": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-background-sync": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", + "integrity": "sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-broadcast-update": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.6.0.tgz", + "integrity": "sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-build": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.6.0.tgz", + "integrity": "sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==", + "dependencies": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.6.0", + "workbox-broadcast-update": "6.6.0", + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-google-analytics": "6.6.0", + "workbox-navigation-preload": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-range-requests": "6.6.0", + "workbox-recipes": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0", + "workbox-streams": "6.6.0", + "workbox-sw": "6.6.0", + "workbox-window": "6.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/workbox-build/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/workbox-build/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/workbox-build/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/workbox-build/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/workbox-build/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/workbox-build/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workbox-build/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/workbox-build/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "node_modules/workbox-build/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/workbox-cacheable-response": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.6.0.tgz", + "integrity": "sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==", + "deprecated": "workbox-background-sync@6.6.0", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-core": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.6.0.tgz", + "integrity": "sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==" + }, + "node_modules/workbox-expiration": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.6.0.tgz", + "integrity": "sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-google-analytics": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.6.0.tgz", + "integrity": "sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==", + "deprecated": "It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained", + "dependencies": { + "workbox-background-sync": "6.6.0", + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-navigation-preload": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.6.0.tgz", + "integrity": "sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-precaching": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.6.0.tgz", + "integrity": "sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==", + "dependencies": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-range-requests": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.6.0.tgz", + "integrity": "sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-recipes": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.6.0.tgz", + "integrity": "sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==", + "dependencies": { + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-routing": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.6.0.tgz", + "integrity": "sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-strategies": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.6.0.tgz", + "integrity": "sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-streams": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.6.0.tgz", + "integrity": "sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==", + "dependencies": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0" + } + }, + "node_modules/workbox-sw": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.6.0.tgz", + "integrity": "sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==" + }, + "node_modules/workbox-webpack-plugin": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.6.0.tgz", + "integrity": "sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==", + "dependencies": { + "fast-json-stable-stringify": "^2.1.0", + "pretty-bytes": "^5.4.1", + "upath": "^1.2.0", + "webpack-sources": "^1.4.3", + "workbox-build": "6.6.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "webpack": "^4.4.0 || ^5.9.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/workbox-window": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.6.0.tgz", + "integrity": "sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==", + "dependencies": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.6.0" + } + }, + "node_modules/worker-timers": { + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.8.tgz", + "integrity": "sha512-R54psRKYVLuzff7c1OTFcq/4Hue5Vlz4bFtNEIarpSiCYhpifHU3aIQI29S84o1j87ePCYqbmEJPqwBTf+3sfw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2", + "worker-timers-broker": "^6.1.8", + "worker-timers-worker": "^7.0.71" + } + }, + "node_modules/worker-timers-broker": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.8.tgz", + "integrity": "sha512-FUCJu9jlK3A8WqLTKXM9E6kAmI/dR1vAJ8dHYLMisLNB/n3GuaFIjJ7pn16ZcD1zCOf7P6H62lWIEBi+yz/zQQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "fast-unique-numbers": "^8.0.13", + "tslib": "^2.6.2", + "worker-timers-worker": "^7.0.71" + } + }, + "node_modules/worker-timers-worker": { + "version": "7.0.71", + "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.71.tgz", + "integrity": "sha512-ks/5YKwZsto1c2vmljroppOKCivB/ma97g9y77MAAz2TBBjPPgpoOiS1qYQKIgvGTr2QYPT3XhJWIB6Rj2MVPQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "engines": { + "node": ">=8.3.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": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.1.tgz", + "integrity": "sha512-pRET7Lao2z+n5R/HduXMio35TncTlSW68WsYBq2Lg1ASspsNGjpwLAsij3RpouyV6+kHMwwwzP0bZPD70/Jx/w==", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} +>>>>>>> origin/main diff --git a/app/package.json b/app/package.json index f1ea92a..ab6f495 100644 --- a/app/package.json +++ b/app/package.json @@ -1,73 +1,73 @@ -{ - "name": "dwinzo-beta", - "version": "0.1.0", - "private": true, - "dependencies": { - "@react-three/csg": "^3.2.0", - "@react-three/drei": "^9.113.0", - "@react-three/fiber": "^8.17.7", - "@react-three/postprocessing": "^2.16.3", - "@testing-library/jest-dom": "^5.17.0", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^13.5.0", - "@turf/turf": "^7.1.0", - "@types/jest": "^27.5.2", - "@types/react": "^18.3.5", - "@types/react-dom": "^18.3.0", - "@use-gesture/react": "^10.3.1", - "chart.js": "^4.4.8", - "glob": "^11.0.0", - "gsap": "^3.12.5", - "leva": "^0.10.0", - "mqtt": "^5.10.4", - "postprocessing": "^6.36.4", - "prompt-sync": "^4.2.0", - "react": "^18.3.1", - "react-chartjs-2": "^5.3.0", - "react-dom": "^18.3.1", - "react-router-dom": "^7.4.0", - "react-scripts": "5.0.1", - "react-toastify": "^10.0.5", - "sass": "^1.78.0", - "socket.io-client": "^4.8.1", - "three": "^0.168.0", - "typescript": "^4.9.5", - "web-vitals": "^2.1.4", - "zustand": "^5.0.0-rc.2" - }, - "scripts": { - "prepare": "husky", - "prestart": "tsc scripts/git-prompt.ts && node scripts/git-prompt.js", - "start": "react-scripts start", - "build": "react-scripts build", - "test": "jest", - "cypress:open": "cypress open", - "cypress:run": "cypress run" - }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "devDependencies": { - "@types/node": "^22.9.1", - "@types/three": "^0.169.0", - "cypress": "^13.14.2", - "dotenv": "^16.4.5", - "husky": "^9.1.6", - "ts-node": "^10.9.2" - } -} +{ + "name": "dwinzo-beta", + "version": "0.1.0", + "private": true, + "dependencies": { + "@react-three/csg": "^3.2.0", + "@react-three/drei": "^9.113.0", + "@react-three/fiber": "^8.17.7", + "@react-three/postprocessing": "^2.16.3", + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^13.5.0", + "@turf/turf": "^7.1.0", + "@types/jest": "^27.5.2", + "@types/react": "^18.3.5", + "@types/react-dom": "^18.3.0", + "@use-gesture/react": "^10.3.1", + "chart.js": "^4.4.8", + "glob": "^11.0.0", + "gsap": "^3.12.5", + "leva": "^0.10.0", + "mqtt": "^5.10.4", + "postprocessing": "^6.36.4", + "prompt-sync": "^4.2.0", + "react": "^18.3.1", + "react-chartjs-2": "^5.3.0", + "react-dom": "^18.3.1", + "react-router-dom": "^7.4.0", + "react-scripts": "5.0.1", + "react-toastify": "^10.0.5", + "sass": "^1.78.0", + "socket.io-client": "^4.8.1", + "three": "^0.168.0", + "typescript": "^4.9.5", + "web-vitals": "^2.1.4", + "zustand": "^5.0.0-rc.2" + }, + "scripts": { + "prepare": "husky", + "prestart": "tsc scripts/git-prompt.ts && node scripts/git-prompt.js", + "start": "react-scripts start", + "build": "GENERATE_SOURCEMAP=false react-scripts build", + "test": "jest", + "cypress:open": "cypress open", + "cypress:run": "cypress run" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@types/node": "^22.9.1", + "@types/three": "^0.169.0", + "cypress": "^13.14.2", + "dotenv": "^16.4.5", + "husky": "^9.1.6", + "ts-node": "^10.9.2" + } +} diff --git a/app/public/index.html b/app/public/index.html index 47d3d43..785ee0f 100644 --- a/app/public/index.html +++ b/app/public/index.html @@ -1,44 +1,44 @@ - - - - - - - - - - - - - Dwinzo (beta) - - - -
-
- - - + + + + + + + + + + + + + Dwinzo (beta) + + + +
+
+ + + diff --git a/app/public/manifest.json b/app/public/manifest.json index 080d6c7..2f2be64 100644 --- a/app/public/manifest.json +++ b/app/public/manifest.json @@ -1,25 +1,25 @@ -{ - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/app/public/robots.txt b/app/public/robots.txt index e9e57dc..9dd52a5 100644 --- a/app/public/robots.txt +++ b/app/public/robots.txt @@ -1,3 +1,3 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/app/src/app.test.tsx b/app/src/app.test.tsx index 49e11a6..e6dd3db 100644 --- a/app/src/app.test.tsx +++ b/app/src/app.test.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import { render, screen } from "@testing-library/react"; -import App from "./app"; - -test("renders learn react link", () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); +import React from "react"; +import { render, screen } from "@testing-library/react"; +import App from "./app"; + +test("renders learn react link", () => { + render(); + const linkElement = screen.getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); diff --git a/app/src/app.tsx b/app/src/app.tsx index c38d48a..f5e19b0 100644 --- a/app/src/app.tsx +++ b/app/src/app.tsx @@ -1,26 +1,26 @@ -import React from "react"; -import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; -import Dashboard from "./pages/Dashboard"; -import Project from "./pages/Project"; -import UserAuth from "./pages/UserAuth"; -import ToastProvider from "./components/templates/ToastProvider"; -import "./styles/main.scss" - -const App: React.FC = () => { - return ( - - - - } - /> - } /> - } /> - - - - ); -}; - -export default App; +import React from "react"; +import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import Dashboard from "./pages/Dashboard"; +import Project from "./pages/Project"; +import UserAuth from "./pages/UserAuth"; +import ToastProvider from "./components/templates/ToastProvider"; +import "./styles/main.scss" + +const App: React.FC = () => { + return ( + + + + } + /> + } /> + } /> + + + + ); +}; + +export default App; diff --git a/app/src/assets/gltf-glb/camera face 2.gltf b/app/src/assets/gltf-glb/camera face 2.gltf index e1c418f..e65dab4 100644 --- a/app/src/assets/gltf-glb/camera face 2.gltf +++ b/app/src/assets/gltf-glb/camera face 2.gltf @@ -1,121 +1,121 @@ -{ - "asset":{ - "generator":"Khronos glTF Blender I/O v3.6.28", - "version":"2.0" - }, - "scene":0, - "scenes":[ - { - "name":"Scene", - "nodes":[ - 0 - ] - } - ], - "nodes":[ - { - "mesh":0, - "name":"Circle" - } - ], - "materials":[ - { - "doubleSided":true, - "name":"Material", - "pbrMetallicRoughness":{ - "baseColorFactor":[ - 0.011087078601121902, - 0.011087078601121902, - 0.011087078601121902, - 1 - ], - "metallicFactor":0, - "roughnessFactor":0.4000000059604645 - } - } - ], - "meshes":[ - { - "name":"Circle", - "primitives":[ - { - "attributes":{ - "POSITION":0, - "NORMAL":1, - "TEXCOORD_0":2 - }, - "indices":3, - "material":0 - } - ] - } - ], - "accessors":[ - { - "bufferView":0, - "componentType":5126, - "count":1910, - "max":[ - 0.29999983310699463, - 0.30012279748916626, - 0.6709707379341125 - ], - "min":[ - -0.30000022053718567, - -0.2998772859573364, - -0.3290294408798218 - ], - "type":"VEC3" - }, - { - "bufferView":1, - "componentType":5126, - "count":1910, - "type":"VEC3" - }, - { - "bufferView":2, - "componentType":5126, - "count":1910, - "type":"VEC2" - }, - { - "bufferView":3, - "componentType":5123, - "count":6084, - "type":"SCALAR" - } - ], - "bufferViews":[ - { - "buffer":0, - "byteLength":22920, - "byteOffset":0, - "target":34962 - }, - { - "buffer":0, - "byteLength":22920, - "byteOffset":22920, - "target":34962 - }, - { - "buffer":0, - "byteLength":15280, - "byteOffset":45840, - "target":34962 - }, - { - "buffer":0, - "byteLength":12168, - "byteOffset":61120, - "target":34963 - } - ], - "buffers":[ - { - "byteLength":73288, - "uri":"data:application/octet-stream;base64,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WQ08PUrllz6Idqi+qs65PW+skz4Sdai+qs65PW+skz4Sdai+px/xPUeJjj4Zdai+px/xPUeJjj4Zdai+px/xPUeJjj4Zdai+zDcVPoSYgz7DQpG+zDcVPoSYgz7DQpG+HKMvPlDfcj41dX2+HKMvPlDfcj41dX2+uVFEPuzPYj4YE2G+uVFEPuzPYj4YE2G+q1BYPjI1Uz5iZka+q1BYPjI1Uz5iZka+0OphPu+USj7UlTu+0OphPu+USj7UlTu+P5thPkDNNz6LXha9NtZqPqY2LD6NXha9Rc1zPlypHz6SXha95CCBPtvQBz6UXha9sTSHPs/23D2YXha9mCWMPpdgpj2bXha9xpiPPotBXz2dXha99qCRPpsz5jydXha9alqSPhSJDrmeXha9FJqRPmFl6LydXha9pouPPt5KYL2VXha9hxKMPpvYpr2TXha9LhyHPoVe3b2QXha99QOBPhj7B76EXha9Yo1zPpLHH76CXha99pNqPtdNLL5+Xha9V1dhPq7dN757Xha9AjtYPo4uQr55Xha9bqlPPtELS754Xha9Va89PvFvW75yXha9kJwpPnDUar5rXha9NocOPlete75lXha9A8/gPYMHhb5eXha9fAOtPX6kib5WXha98SwwPbhwjr5MXha968iqs9wUkL4/Xha9FS0wvbdwjr4yXha9jQOtvX6kib43Xha9Fc/gvYMHhb4wXha9RIcOvk+te74oXha9nZwpvmnUar4iXha9Xq89vu5vW74cXha9e6lPvssLS74WXha9EztYvoMuQr4WXha9YVdhvq7dN74TXha9/pNqvtRNLL4QXha9a41zvovHH74MXha9+gOBvg/7B74JXha9MhyHvm5e3b0OXha9jBKMvoPYpr0LXha9p4uPvrpKYL0IXha9FZqRvgpl6LwQXha9a1qSvqdrDrkQXha9+KCRvs8z5jwQXha9x5iPvqNBXz0QXha9mSWMvp5gpj0TXha9sTSHvs723D0WXha95SCBvt3QBz4ZXha9Ts1zvl+pHz4cXha9PtZqvqQ2LD4fXha9RpthvkPNNz4iXha99H9YvmwkQj4lXha93e5PvkYHSz4mXha9VPQ9vm52Wz4zXha9ld4pvojmaj4wXha9BcIOvmTNez44Xha9tC7hveYdhT5AXha9m0+tveK+iT5HXha9qn0wvWWPjj5SXha9wG8KMA01kD5fXha9nX0wPWWPjj5rXha9kE+tPeK+iT52Xha9ti7hPeUdhT59Xha9AsIOPmLNez6FXha9kN4pPormaj6OXha9TvQ9Pm52Wz6KXha92+5PPkMHSz6HXha98H9YPmckQj6IXha9QJthPkDNNz43efm8QJthPkDNNz43efm8N9ZqPqY2LD46efm8N9ZqPqY2LD46efm8R81zPlypHz5Aefm8R81zPlypHz5Aefm85SCBPtvQBz5Hefm85SCBPtvQBz5Hefm8sjSHPs/23D1Oefm8sjSHPs/23D1Oefm8mSWMPpdgpj1Uefm8mSWMPpdgpj1Uefm8x5iPPotBXz1Yefm8x5iPPotBXz1Yefm896CRPp0z5jxKefm896CRPp0z5jxKefm8alqSPrKIDrlKefm8alqSPrKIDrlKefm8FZqRPmBl6LxKefm8FZqRPmBl6LxKefm8pouPPt5KYL04efm8pouPPt5KYL04efm8iBKMPpvYpr00efm8iBKMPpvYpr00efm8LxyHPoVe3b0tefm8LxyHPoVe3b0tefm89gOBPhj7B74mefm89gOBPhj7B74mefm8ZI1zPpLHH74hefm8ZI1zPpLHH74hefm895NqPtdNLL4befm895NqPtdNLL4befm8WVdhPq7dN74Vefm8WVdhPq7dN74Vefm8BDtYPo4uQr4Refm8BDtYPo4uQr4Refm8b6lPPtELS74Mefm8b6lPPtELS74Mefm8Va89PvFvW74Befm8Va89PvFvW74Befm8kJwpPnDUar74ePm8kJwpPnDUar74ePm8NocOPlete77oePm8NocOPlete77oePm8Bc/gPYMHhb7XePm8Bc/gPYMHhb7XePm8fgOtPX6kib7MePm8fgOtPX6kib7MePm88SwwPbhwjr61ePm88SwwPbhwjr61ePm8y0+cs9wUkL6bePm8y0+cs9wUkL6bePm8FS0wvbdwjr6CePm8FS0wvbdwjr6CePm8iwOtvX6kib58ePm8iwOtvX6kib58ePm8E8/gvYMHhb5xePm8E8/gvYMHhb5xePm8RIcOvk+te75fePm8RIcOvk+te75fePm8nZwpvmnUar5QePm8nZwpvmnUar5QePm8Xq89vu5vW75VePm8Xq89vu5vW75VePm8ealPvssLS75MePm8ealPvssLS75MePm8ETtYvoMuQr5HePm8ETtYvoMuQr5HePm8YFdhvq7dN75DePm8YFdhvq7dN75DePm8/ZNqvtRNLL48ePm8/ZNqvtRNLL48ePm8aY1zvovHH743ePm8aY1zvovHH743ePm8+QOBvg/7B74wePm8+QOBvg/7B74wePm8MhyHvm5e3b0pePm8MhyHvm5e3b0pePm8ixKMvoPYpr0kePm8ixKMvoPYpr0kePm8pouPvrpKYL0gePm8pouPvrpKYL0gePm8FZqRvgll6LwuePm8FZqRvgll6LwuePm8alqSvkNrDrkuePm8alqSvkNrDrkuePm896CRvtEz5jwuePm896CRvtEz5jwuePm8x5iPvqNBXz0/ePm8x5iPvqNBXz0/ePm8mCWMvp5gpj1CePm8mCWMvp5gpj1CePm8sDSHvs723D1JePm8sDSHvs723D1JePm85CCBvt3QBz5QePm85CCBvt3QBz5QePm8TM1zvl+pHz5XePm8TM1zvl+pHz5XePm8PdZqvqQ2LD5dePm8PdZqvqQ2LD5dePm8RJthvkPNNz5gePm8RJthvkPNNz5gePm8839YvmwkQj5mePm8839YvmwkQj5mePm83O5PvkYHSz5pePm83O5PvkYHSz5pePm8VPQ9vm52Wz51ePm8VPQ9vm52Wz51ePm8ld4pvojmaj6AePm8ld4pvojmaj6AePm8BcIOvmTNez6OePm8BcIOvmTNez6OePm8si7hveYdhT6gePm8si7hveYdhT6gePm8mU+tveK+iT6sePm8mU+tveK+iT6sePm8qn0wvWWPjj7BePm8qn0wvWWPjj7BePm8+t/4MQ01kD7cePm8+t/4MQ01kD7cePm8nX0wPWWPjj70ePm8nX0wPWWPjj70ePm8kk+tPeK+iT77ePm8kk+tPeK+iT77ePm8uC7hPeUdhT4Hefm8uC7hPeUdhT4Hefm8AsIOPmLNez4Xefm8AsIOPmLNez4Xefm8kN4pPormaj4nefm8kN4pPormaj4nefm8TvQ9Pm52Wz4hefm8TvQ9Pm52Wz4hefm83O5PPkMHSz4uefm83O5PPkMHSz4uefm88n9YPmckQj4xefm88n9YPmckQj4xefm8DmNEPksDID50Tki0DmNEPksDID50Tki0DmNEPksDID50Tki0DmNEPksDID50Tki0+mtMPursFT7s/FC0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AACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwUAAwABAAEAPwA9AD0AOwA5ADkANwA1ADUAMwAxADEALgAsACwAKgAoACgAJgAkACQAIgAgACAAHgAcABwAGgAYABgAFgAUABQAEgAQABAADwANAA0ACwAJAAkABwAFAAUAAQA9AD0AOQA1ADUAMQAsACwAKAAkACQAIAAcABwAGAAUABQAEAANAA0ACQAFAAUAPQA1ADUALAAkACQAHAAUABQADQAFAAUANQAkACQAFAAFAFEAUwCTAFEAkwCRABsAHQBcABsAXABaAAAAAgBBAAAAQQBDADYAOAB5ADYAeQB3AB0AHwBeAB0AXgBcAAIABABFAAIARQBBADgAOgB7ADgAewB5AB8AIQBgAB8AYABeAAQABgBHAAQARwBFADoAPAB9ADoAfQB7ACEAIwBiACEAYgBgAAYACABJAAYASQBHADwAPgB/ADwAfwB9ACMAJQBkACMAZABiAAgACgBLAAgASwBJAD4AAABDAD4AQwB/ACUAJwBmACUAZgBkAAoADABNAAoATQBLACcAKQBoACcAaABmAAwADgBPAAwATwBNACkAKwBqACkAagBoAA4AEQBQAA4AUABPACsALQBsACsAbABqABEAEwBSABEAUgBQAC0ALwBuAC0AbgBsABMAFQBUABMAVABSAC8AMABxAC8AcQBuABUAFwBWABUAVgBUADAAMgBzADAAcwBxABcAGQBYABcAWABWADIANAB1ADIAdQBzABkAGwBaABkAWgBYADQANgB3ADQAdwB1AJYAmADYAJYA2ADWAG0AbwCvAG0ArwCtAFMAVQCVAFMAlQCTAG8AcACwAG8AsACvAFUAVwCXAFUAlwCVAHAAcgCyAHAAsgCwAFcAWQCZAFcAmQCXAHIAdAC0AHIAtACyAFkAWwCbAFkAmwCZAHQAdgC2AHQAtgC0AFsAXQCdAFsAnQCbAEIAQACAAEIAgACCAHYAeAC4AHYAuAC2AF0AXwCfAF0AnwCdAEAARACEAEAAhACAAHgAegC6AHgAugC4AF8AYQChAF8AoQCfAEQARgCGAEQAhgCEAHoAfAC8AHoAvAC6AGEAYwCjAGEAowChAEYASACIAEYAiACGAHwAfgC+AHwAvgC8AGMAZQClAGMApQCjAEgASgCKAEgAigCIAH4AQgCCAH4AggC+AGUAZwCnAGUApwClAEoATACMAEoAjACKAGcAaQCpAGcAqQCnAEwATgCOAEwAjgCMAGkAawCrAGkAqwCpAE4AUQCRAE4AkQCOAGsAbQCtAGsArQCrAN0A3wAfAd0AHwEdAbMAtQD1ALMA9QDzAJgAmgDaAJgA2gDYALUAtwD3ALUA9wD1AJoAnADcAJoA3ADaAIMAgQDBAIMAwQDDALcAuQD5ALcA+QD3AJwAngDeAJwA3gDcAIEAhQDFAIEAxQDBALkAuwD7ALkA+wD5AJ4AoADgAJ4A4ADeAIUAhwDHAIUAxwDFALsAvQD9ALsA/QD7AKAAogDiAKAA4gDgAIcAiQDJAIcAyQDHAL0AvwD/AL0A/wD9AKIApADkAKIA5ADiAIkAiwDLAIkAywDJAL8AgwDDAL8AwwD/AKQApgDmAKQA5gDkAIsAjQDNAIsAzQDLAKYAqADoAKYA6ADmAI0AjwDPAI0AzwDNAKgAqgDqAKgA6gDoAI8AkADQAI8A0ADPAKoArADsAKoA7ADqAJAAkgDSAJAA0gDQAKwArgDuAKwA7gDsAJIAlADUAJIA1ADSAK4AsQDxAK4A8QDuAJQAlgDWAJQA1gDUALEAswDzALEA8wDxACIBJAFkASIBZAFiAcAAxAAEAcAABAEAAfgA+gA6AfgAOgE4Ad8A4QAhAd8AIQEfAcQAxgAGAcQABgEEAfoA/AA8AfoAPAE6AeEA4wAjAeEAIwEhAcYAyAAIAcYACAEGAfwA/gA+AfwAPgE8AeMA5QAlAeMAJQEjAcgAygAKAcgACgEIAf4AwgACAf4AAgE+AeUA5wAnAeUAJwElAcoAzAAMAcoADAEKAecA6QApAecAKQEnAcwAzgAOAcwADgEMAekA6wArAekAKwEpAc4A0QARAc4AEQEOAesA7QAtAesALQErAdEA0wATAdEAEwERAe0A7wAvAe0ALwEtAdMA1QAVAdMAFQETAe8A8AAwAe8AMAEvAdUA1wAXAdUAFwEVAfAA8gAyAfAAMgEwAdcA2QAZAdcAGQEXAfIA9AA0AfIANAEyAdkA2wAbAdkAGwEZAfQA9gA2AfQANgE0AdsA3QAdAdsAHQEbAcIAwAAAAcIAAAECAfYA+AA4AfYAOAE2AVEBUwGJAVEBiQGIAQkBCwFLAQkBSwFJAT8BAwFDAT8BQwF/ASQBJgFmASQBZgFkAQsBDQFNAQsBTQFLASYBKAFoASYBaAFmAQ0BDwFPAQ0BTwFNASgBKgFqASgBagFoAQ8BEAFQAQ8BUAFPASoBLAFsASoBbAFqARABEgFSARABUgFQASwBLgFuASwBbgFsARIBFAFUARIBVAFSAS4BMQFxAS4BcQFuARQBFgFWARQBVgFUATEBMwFzATEBcwFxARYBGAFYARYBWAFWATMBNQF1ATMBdQFzARgBGgFaARgBWgFYATUBNwF3ATUBdwF1ARoBHAFcARoBXAFaAQMBAQFBAQMBQQFDATcBOQF5ATcBeQF3ARwBHgFeARwBXgFcAQEBBQFFAQEBRQFBATkBOwF7ATkBewF5AR4BIAFgAR4BYAFeAQUBBwFHAQUBRwFFATsBPQF9ATsBfQF7ASABIgFiASABYgFgAQcBCQFJAQcBSQFHAT0BPwF/AT0BfwF9AYsBjAGsAYsBrAGrAW0BbwGXAW0BlwGWAVMBVQGKAVMBigGJAW8BcAGYAW8BmAGXAVUBVwGLAVUBiwGKAXABcgGZAXABmQGYAVcBWQGMAVcBjAGLAXIBdAGaAXIBmgGZAVkBWwGNAVkBjQGMAXQBdgGbAXQBmwGaAVsBXQGOAVsBjgGNAUIBQAGAAUIBgAGBAXYBeAGcAXYBnAGbAV0BXwGPAV0BjwGOAUABRAGCAUABggGAAXgBegGdAXgBnQGcAV8BYQGQAV8BkAGPAUQBRgGDAUQBgwGCAXoBfAGeAXoBngGdAWEBYwGRAWEBkQGQAUYBSAGEAUYBhAGDAXwBfgGfAXwBnwGeAWMBZQGSAWMBkgGRAUgBSgGFAUgBhQGEAX4BQgGBAX4BgQGfAWUBZwGTAWUBkwGSAUoBTAGGAUoBhgGFAWcBaQGUAWcBlAGTAUwBTgGHAUwBhwGGAWkBawGVAWkBlQGUAU4BUQGIAU4BiAGHAWsBbQGWAWsBlgGVAZkBmgG6AZkBugG5AYwBjQGtAYwBrQGsAZoBmwG7AZoBuwG6AY0BjgGuAY0BrgGtAYEBgAGgAYEBoAGhAZsBnAG8AZsBvAG7AY4BjwGvAY4BrwGuAYABggGiAYABogGgAZwBnQG9AZwBvQG8AY8BkAGwAY8BsAGvAYIBgwGjAYIBowGiAZ0BngG+AZ0BvgG9AZABkQGxAZABsQGwAYMBhAGkAYMBpAGjAZ4BnwG/AZ4BvwG+AZEBkgGyAZEBsgGxAYQBhQGlAYQBpQGkAZ8BgQGhAZ8BoQG/AZIBkwGzAZIBswGyAYUBhgGmAYUBpgGlAZMBlAG0AZMBtAGzAYYBhwGnAYYBpwGmAZQBlQG1AZQBtQG0AYcBiAGoAYcBqAGnAZUBlgG2AZUBtgG1AYgBiQGpAYgBqQGoAZYBlwG3AZYBtwG2AYkBigGqAYkBqgGpAZcBmAG4AZcBuAG3AYoBiwGrAYoBqwGqAZgBmQG5AZgBuQG4AcUBxwEHAsUBBwIFAqIBowHGAaIBxgHEAaMBpAHIAaMByAHGAYMCgQJMAoMCTAJKAvsB/QE9AvsBPQI7AuAB4gEiAuABIgIgAscByQEJAscBCQIHAv0B/wE/Av0BPwI9AuIB5AEkAuIBJAIiAskBywELAskBCwIJAv8BwwEDAv8BAwI/AuQB5gEmAuQBJgIkAssBzQENAssBDQILAuYB6AEoAuYBKAImAs0BzwEPAs0BDwINAugB6gEqAugBKgIoAs8B0AEQAs8BEAIPAuoB7AEsAuoBLAIqAtAB0gESAtABEgIQAuwB7gEuAuwBLgIsAtIB1AEUAtIBFAISAu4B8QExAu4BMQIuAtQB1gEWAtQBFgIUAvEB8wEzAvEBMwIxAtYB2AEYAtYBGAIWAvMB9QE1AvMBNQIzAtgB2gEaAtgBGgIYAvUB9wE3AvUBNwI1AtoB3AEcAtoBHAIaAsMBwQEBAsMBAQIDAvcB+QE5AvcBOQI3AtwB3gEeAtwBHgIcAsEBxQEFAsEBBQIBAvkB+wE7AvkBOwI5At4B4AEgAt4BIAIeAuQG4QZYAowCigJoAowCaAJmAoECkQJOAoECTgJMAooClgJqAooCagJoApECmgJRApECUQJOApYCngJsApYCbAJqApoCogJTApoCUwJRAp4CpgJuAp4CbgJsAqICqgJVAqICVQJTAqYCrQJwAqYCcAJuAqoCsgJXAqoCVwJVAq0CtQJxAq0CcQJwArICugJZArICWQJXArUCvQJzArUCcwJxAroCwgJbAroCWwJZAr0CxQJ1Ar0CdQJzAsICygJdAsICXQJbAs8CzQJAAs8CQAJCAsUC1QJ3AsUCdwJ1AsoC2gJfAsoCXwJdAs0C3QJEAs0CRAJAAtUC4QJ5AtUCeQJ3AtoC5gJhAtoCYQJfAt0C6QJGAt0CRgJEAuEC7QJ7AuECewJ5AuYC8gJjAuYCYwJhAukC9QJIAukCSAJGAu0C+QJ9Au0CfQJ7AvIC/gJlAvICZQJjAvUCgwJKAvUCSgJIAvkCzwJCAvkCQgJ9Av4CjAJmAv4CZgJlAiUCJwKOAiUCjgL8AqkCoQKhA6kCoQOpAz4CAgLRAj4C0QL3AikDMQOvAykDrwOnAwgCCgKFAggChQLzAp8CpwItBJ8CLQQxBCMCJQL8AiMC/ALwAi8DJwNTBC8DUwRXBDwCPgL3AjwC9wLrAq4CpQKlA64CpQOuAwYCCALzAgYC8wLnAiUDLgOsAyUDrAOjAyECIwLwAiEC8ALkAqMCrAIsBKMCLAQvBDoCPALrAjoC6wLfAiwDIwNRBCwDUQRWBAQCBgLnAgQC5wLbArECqQKpA7ECqQOxAx8CIQLkAh8C5ALYAiEDKQOnAyEDpwOfAzgCOgLfAjgC3wLTAqcCrwIpBKcCKQQtBAACBALbAgAC2wLLAicDHwNPBCcDTwRTBB0CHwLYAh0C2ALIArYCrgKuA7YCrgO2AzYCOALTAjYC0wLDAh0DJQOjAx0DowObAwICAALLAgICywLRAqwCtAIoBKwCKAQsBBsCHQLIAhsCyALAAiMDGwNNBCMDTQRRBDQCNgLDAjQCwwK7ArkCsQKxA7kCsQO5AxkCGwLAAhkCwAK4AhkDIQOfAxkDnwOXAzICNAK7AjICuwKzAq8CtwIlBK8CJQQpBBcCGQK4AhcCuAKwAh8DFwNLBB8DSwRPBDACMgKzAjACswKrAr4CtgK2A74CtgO+AxUCFwKwAhUCsAKoAn0DCwNFBH0DRQT7Ay8CMAKrAi8CqwKkAhUDHQObAxUDmwOTAxMCFQKoAhMCqAKgArQCvAIkBLQCJAQoBC0CLwKkAi0CpAKcAg0DewN9BA0DfQSLAxECEwKgAhECoAKYAhsDEwNJBBsDSQRNBCsCLQKcAisCnAKUAsECuQK5A8ECuQPBAw4CEQKYAg4CmAKPAnoDUANoBHoDaAT4AykCKwKUAikClAKIAhIDGQOXAxIDlwOQAwwCDgKPAgwCjwJ/ArcCvwIhBLcCIQQlBCcCKQKIAicCiAKOAlIDeAN8BFIDfATQAwoCDAJ/AgoCfwKFAhcDEANIBBcDSARLBMYCvgK+A8YCvgPGAwUD/wIBAwUDAQMDA3YDBANCBHYDQgT0Aw4DCAMKAw4DCgMMAwkDFQOTAwkDkwOHA/8CDwMRA/8CEQMBA7wCxAIgBLwCIAQkBAgDFAMWAwgDFgMKAwYDdAN6BAYDegSEAw8DGAMaAw8DGgMRAxMDBwNDBBMDQwRJBBQDHAMeAxQDHgMWA8kCwQLBA8kCwQPJAxgDIAMiAxgDIgMaA3EDfQP7A3ED+wPvAxwDJAMmAxwDJgMeAwIDEgOQAwIDkAOAAyADKAMqAyADKgMiA78CxwIdBL8CHQQhBCQDKwMtAyQDLQMmA3sDbwN3BHsDdwR9BCgDMAMyAygDMgMqAxADAANABBADQARIBCsDMwM1AysDNQMtA84C0AIGBM4CBgTOAzADOAM6AzADOgMyA24DegP4A24D+APsAzMDOwM9AzMDPQM1AwsDCQOHAwsDhwNFBDgDQANCAzgDQgM6A9ICzAIcBNICHATSAzsDQwNFAzsDRQM9A3gDbAN2BHgDdgR8BEADSANKA0ADSgNCAwcDDQOLAwcDiwNDBFEDSwNNA1EDTQNPA9YCxgLGA9YCxgPWA0MDUwNVA0MDVQNFA2oDdgP0A2oD9APoA0gDWANaA0gDWgNKAwQDAgOAAwQDgANCBEsDWwNdA0sDXQNNA8QC1AIaBMQCGgQgBFMDXwNhA1MDYQNVA3QDaAN0BHQDdAR6BFgDZANmA1gDZgNaAwADBgOEAwADhANABFsDZwNpA1sDaQNdA9kCyQLJA9kCyQPZA18DawNtA18DbQNhA2UDcQPvA2UD7wPjA2QDcANyA2QDcgNmA8cC1wIXBMcCFwQdBGcDcwN1A2cDdQNpA28DYwNxBG8DcQR3BGsDdwN5A2sDeQNtA94CzgLOA94CzgPeA3ADfAN+A3ADfgNyA2IDbgPsA2ID7APgA3MDBQMDA3MDAwN1A8wC3AIWBMwCFgQcBHcDUQNPA3cDTwN5A2wDYANwBGwDcAR2BHwDDgMMA3wDDAN+A/wDRgQCBPwDAgT+A/cDZwQFBPcDBQT5A/MDQQQJBPMDCQT1A/AD/AP+A/AD/gPyA+sD9wP5A+sD+QPtA+cD8wP1A+cD9QPpA+QD8APyA+QD8gPmA98D6wPtA98D7QPhA9sD5wPpA9sD6QPdA9gD5APmA9gD5gPaA9MD3wPhA9MD4QPVA8sD2wPdA8sD3QPNA8gD2APaA8gD2gPKA8MD0wPVA8MD1QPFA2cEywPNA2cEzQMFBMADyAPKA8ADygPCA7sDwwPFA7sDxQO9A7gDwAPCA7gDwgO6A7MDuwO9A7MDvQO1A7ADuAO6A7ADugOyA6sDswO1A6sDtQOtA6gDsAOyA6gDsgOqA6QDqwOtA6QDrQOmA6ADqAOqA6ADqgOiA5wDpAOmA5wDpgOeA5gDoAOiA5gDogOaA5QDnAOeA5QDngOWA48DmAOaA48DmgORA4gDlAOWA4gDlgOKA38DjwORA38DkQOBA0YEiAOKA0YEigMCBEEEfwOBA0EEgQMJBIUDPQQ/BIUDPwSDA44DPAREBI4DRASMAz0EOQRHBD0ERwQ/BDwEOARKBDwESgREBDkENgRMBDkETARHBDgENAROBDgETgRKBDYEMgRQBDYEUARMBDQEMARSBDQEUgROBDIELgRUBDIEVARQBDAEKwRVBDAEVQRSBC4EKgRYBC4EWARUBCsEJwRZBCsEWQRVBCoEJgRcBCoEXARYBCcEIwRdBCcEXQRZBCYEIgRgBCYEYARcBCMEHwRhBCMEYQRdBCIEHgRkBCIEZARgBNEDGwRlBNEDZQTPAx8EGQRpBB8EaQRhBB4EGARsBB4EbARkBBsEFQRtBBsEbQRlBBkEEwRvBBkEbwRpBBgEEgRyBBgEcgRsBBUEDwRzBBUEcwRtBBMEDQR1BBMEdQRvBBIEDAR4BBIEeARyBA8EBwR5BA8EeQRzBA0EAwR7BA0EewR1BAwEAAR+BAwEfgR4BAcEhQODAwcEgwN5BAME0QPPAwMEzwN7BAAEjgOMAwAEjAN+BDQDLANWBDQDVgRaBJsCowIvBJsCLwQzBC4DNgO0Ay4DtAOsA6UCnQKdA6UCnQOlAzcDLwNXBDcDVwRbBJcCnwIxBJcCMQQ1BDEDOQO3AzEDtwOvA6ECmQKZA6ECmQOhAzwDNANaBDwDWgReBPsCjQKNA/sCjQP/A5MCmwIzBJMCMwQ3BDYDPgO8AzYDvAO0A4sC/QL9A4sC/QMBBJ0ClQKVA50ClQOdAz8DNwNbBD8DWwRfBPgC0gLSA/gC0gMEBJAClwI1BJACNQQ6BDkDQQO/AzkDvwO3A9AC+gL6A9AC+gMGBJkCkgKSA5kCkgOZA0QDPANeBEQDXgRiBPQChgKGA/QChgMIBIcCkwI3BIcCNwQ7BD4DRgPEAz4DxAO8A4QC9gL2A4QC9gMKBJUCiQKJA5UCiQOVA0cDPwNfBEcDXwRjBO8C+wL/A+8C/wMLBIACkAI6BIACOgQ+BEEDSQPHA0EDxwO/A/0C8QLxA/0C8QP9A5ICggKCA5ICggOSA0wDUgPQA0wD0ANmBOwC+AIEBOwCBAQOBI0ChwI7BI0COwSNA1ADTgPMA1ADzANoBPoC7gLuA/oC7gP6A4kCiwIBBIkCAQSJA1QDRANiBFQDYgRqBOgC9AIIBOgCCAQQBIYCgAI+BIYCPgSGA0YDVgPUA0YD1APEA/YC6gLqA/YC6gP2A4IChAIKBIICCgSCA1cDRwNjBFcDYwRrBOMC7wILBOMCCwQRBEkDWQPXA0kD1wPHA/EC5QLlA/EC5QPxA1wDTANmBFwDZgRuBOAC7AIOBOACDgQUBE4DXgPcA04D3APMA+4C4gLiA+4C4gPuA2ADVANqBGADagRwBNwC6AIQBNwCEAQWBFYDYgPgA1YD4APUA+oC3gLeA+oC3gPqA2MDVwNrBGMDawRxBNcC4wIRBNcCEQQXBFkDZQPjA1kD4wPXA+UC2QLZA+UC2QPlA2gDXANuBGgDbgR0BNQC4AIUBNQCFAQaBF4DagPoA14D6APcA+IC1gLWA+IC1gPiA6QBpQHKAaQBygHIAaUBpgHMAaUBzAHKAaYBpwHOAaYBzgHMAacBqAHRAacB0QHOAagBqQHTAagB0wHRAakBqgHVAakB1QHTAaoBqwHXAaoB1wHVAasBrAHZAasB2QHXAawBrQHbAawB2wHZAa0BrgHdAa0B3QHbAa4BrwHfAa4B3wHdAa8BsAHhAa8B4QHfAbABsQHjAbAB4wHhAbEBsgHlAbEB5QHjAbIBswHnAbIB5wHlAbMBtAHpAbMB6QHnAbQBtQHrAbQB6wHpAbUBtgHtAbUB7QHrAbYBtwHvAbYB7wHtAbcBuAHwAbcB8AHvAbgBuQHyAbgB8gHwAbkBugH0AbkB9AHyAboBuwH2AboB9gH0AbsBvAH4AbsB+AH2AbwBvQH6AbwB+gH4Ab0BvgH8Ab0B/AH6Ab4BvwH+Ab4B/gH8Ab8BoQHCAb8BwgH+AaEBoAHAAaEBwAHCAaABogHEAaABxAHAAesEQAVBBesEQQXuBLYEJgUnBbYEJwW5BIIEDAUNBYIEDQWEBO4EQQVCBe4EQgXwBLkEJwUoBbkEKAW8BIQEDQUOBYQEDgWGBPAEQgVDBfAEQwXyBLwEKAUpBbwEKQW+BIYEDgUPBYYEDwWIBPIEQwVEBfIERAX0BL4EKQUqBb4EKgW/BIgEDwUQBYgEEAWKBPQERAVFBfQERQX2BL8EKgUrBb8EKwXBBIoEEAURBYoEEQWMBPYERQVGBfYERgX5BMEEKwUsBcEELAXDBIwEEQUSBYwEEgWOBPkERgVHBfkERwX7BMMELAUtBcMELQXFBI4EEgUTBY4EEwWQBPsERwVIBfsESAX9BMUELQUuBcUELgXHBJAEEwUUBZAEFAWSBP0ESAVJBf0ESQX/BMcELgUvBccELwXJBJIEFAUVBZIEFQWUBP8ESQVKBf8ESgUBBckELwUwBckEMAXLBJQEFQUWBZQEFgWWBAEFSgVLBQEFSwUDBcsEMAUxBcsEMQXNBJYEFgUXBZYEFwWYBAMFSwVMBQMFTAUGBc0EMQUyBc0EMgXPBJgEFwUYBZgEGAWaBAYFTAVNBQYFTQUIBc8EMgUzBc8EMwXRBJoEGAUZBZoEGQWcBAgFTQVOBQgFTgUKBdEEMwU0BdEENAXTBJwEGQUaBZwEGgWeBAoFTgULBQoFCwWABNMENAU1BdMENQXVBJ4EGgUbBZ4EGwWgBNUENQU2BdUENgXXBKAEGwUcBaAEHAWiBNcENgU3BdcENwXZBKIEHAUdBaIEHQWkBNkENwU4BdkEOAXbBKQEHQUeBaQEHgWmBNsEOAU5BdsEOQXdBKYEHgUfBaYEHwWnBN0EOQU6Bd0EOgXfBKcEHwUgBacEIAWpBN8EOgU7Bd8EOwXhBKkEIAUhBakEIQWsBOEEOwU8BeEEPAXjBKwEIQUiBawEIgWvBOMEPAU9BeMEPQXlBK8EIgUjBa8EIwWxBOUEPQU+BeUEPgXnBLEEIwUkBbEEJAWyBOcEPgU/BecEPwXpBLIEJAUlBbIEJQW0BOkEPwVABekEQAXrBLQEJQUmBbQEJgW2BIAECwUMBYAEDAWCBD8FtwW5BT8FuQVABSUFgwWFBSUFhQUmBQsFUAVSBQsFUgUMBUAFuQW7BUAFuwVBBSYFhQWHBSYFhwUnBQwFUgVUBQwFVAUNBUEFuwW9BUEFvQVCBScFhwWJBScFiQUoBQ0FVAVWBQ0FVgUOBUIFvQW/BUIFvwVDBSgFiQWLBSgFiwUpBQ4FVgVYBQ4FWAUPBUMFvwXBBUMFwQVEBSkFiwWNBSkFjQUqBQ8FWAVaBQ8FWgUQBUQFwQXDBUQFwwVFBSoFjQWPBSoFjwUrBRAFWgVcBRAFXAURBUUFwwXGBUUFxgVGBSsFjwWRBSsFkQUsBREFXAVeBREFXgUSBUYFxgXIBUYFyAVHBSwFkQWTBSwFkwUtBRIFXgVgBRIFYAUTBUcFyAXKBUcFygVIBS0FkwWVBS0FlQUuBRMFYAViBRMFYgUUBUgFygXMBUgFzAVJBS4FlQWXBS4FlwUvBRQFYgVkBRQFZAUVBUkFzAXOBUkFzgVKBS8FlwWZBS8FmQUwBRUFZAVmBRUFZgUWBUoFzgXQBUoF0AVLBTAFmQWbBTAFmwUxBRYFZgVoBRYFaAUXBUsF0AXSBUsF0gVMBTEFmwWdBTEFnQUyBRcFaAVqBRcFagUYBUwF0gXUBUwF1AVNBTIFnQWfBTIFnwUzBRgFagVsBRgFbAUZBU0F1AXWBU0F1gVOBTMFnwWhBTMFoQU0BRkFbAVuBRkFbgUaBU4F1gVQBU4FUAULBTQFoQWjBTQFowU1BRoFbgVwBRoFcAUbBTUFowWlBTUFpQU2BRsFcAVyBRsFcgUcBTYFpQWnBTYFpwU3BRwFcgV0BRwFdAUdBTcFpwWpBTcFqQU4BR0FdAV2BR0FdgUeBTgFqQWrBTgFqwU5BR4FdgV4BR4FeAUfBTkFqwWtBTkFrQU6BR8FeAV6BR8FegUgBToFrQWvBToFrwU7BSAFegV8BSAFfAUhBTsFrwWxBTsFsQU8BSEFfAV+BSEFfgUiBTwFsQWzBTwFswU9BSIFfgWABSIFgAUjBT0FswW1BT0FtQU+BSMFgAWBBSMFgQUkBT4FtQW3BT4FtwU/BSQFgQWDBSQFgwUlBa4FlAaYBq4FmAawBXkFLgYzBnkFMwZ7BbAFmAacBrAFnAayBXsFMwY3BnsFNwZ9BbIFnAagBrIFoAa0BX0FNwY7Bn0FOwZ/BbQFoAakBrQFpAa2BX8FOwY9Bn8FPQaCBbYFpAaoBrYFqAa4BYIFPQZBBoIFQQaEBbgFqAasBrgFrAa6BYQFQQZEBoQFRAaGBU8F2gXeBU8F3gVRBboFrAawBroFsAa8BYYFRAZIBoYFSAaIBVEF3gXiBVEF4gVTBbwFsAa0BrwFtAa+BYgFSAZMBogFTAaKBVMF4gXmBVMF5gVVBb4FtAa4Br4FuAbABYoFTAZQBooFUAaMBVUF5gXqBVUF6gVXBcAFuAa8BsAFvAbCBYwFUAZUBowFVAaOBVcF6gXuBVcF7gVZBcIFvAbABsIFwAbEBY4FVAZYBo4FWAaQBVkF7gXyBVkF8gVbBcQFwAbFBsQFxQbFBZAFWAZcBpAFXAaSBVsF8gX2BVsF9gVdBcUFxQbJBsUFyQbHBZIFXAZgBpIFYAaUBV0F9gX6BV0F+gVfBccFyQbOBscFzgbJBZQFYAZkBpQFZAaWBV8F+gX+BV8F/gVhBckFzgbSBskF0gbLBZYFZAZoBpYFaAaYBWEF/gUCBmEFAgZjBcsF0gbXBssF1wbNBZgFaAZsBpgFbAaaBWMFAgYGBmMFBgZlBc0F1wbbBs0F2wbPBZoFbAZwBpoFcAacBWUFBgYKBmUFCgZnBc8F2wbgBs8F4AbRBZwFcAZ0BpwFdAaeBWcFCgYOBmcFDgZpBdEF4AblBtEF5QbTBZ4FdAZ4Bp4FeAagBWkFDgYRBmkFEQZrBdMF5QbpBtMF6QbVBaAFeAZ8BqAFfAaiBWsFEQYVBmsFFQZtBdUF6QbaBdUF2gVPBaIFfAaABqIFgAakBW0FFQYZBm0FGQZvBaQFgAaEBqQFhAamBW8FGQYdBm8FHQZxBaYFhAaIBqYFiAaoBXEFHQYhBnEFIQZzBagFiAaMBqgFjAaqBXMFIQYmBnMFJgZ1BaoFjAaQBqoFkAasBXUFJgYqBnUFKgZ3BawFkAaUBqwFlAauBXcFKgYuBncFLgZ5BegG5AZYAuEG3AZWAuEGVgJYAt0G2AZXAtgG1AZVAtgGVQJXAtMGzwZUAs8GywZSAs8GUgJUAssGxgZQAssGUAJSAsYGwQZQAsEGvQZPAsEGTwJQAr0GuQZNAr0GTQJPArkGtQZNArUGsQZLArUGSwJNArEGrQZLAq0GqQZJAq0GSQJLAqkGpQZJAqUGoQZJAqEGnQZJAp0GmQZHAp0GRwJJApkGlQZHApUGkQZFApUGRQJHApEGjQZFAo0GiQZBAo0GQQJFAokGhQZBAoUGgQZDAoUGQwJBAoEGfQZDAn0GeQZ+An0GfgJDAnkGdQZ8AnkGfAJ+AnUGcQZ8AnEGbQZ6AnEGegJ8Am0GaQZ6AmkGZQZ4AmkGeAJ6AmUGYQZ4AmEGXQZ4Al0GWQZ4AlkGVQZ2AlkGdgJ4AlUGUQZ2AlEGTQZ0AlEGdAJ2Ak0GSQZ0AkkGRgZyAkkGcgJ0AkYGQgZvAkYGbwJyAkIGPwZvAj8GOgZtAj8GbQJvAjoGNgZrAjoGawJtAjYGMgZrAjIGLwZpAjIGaQJrAi8GKwZnAi8GZwJpAisGJwZnAicGIgZnAiMGHgZmAiMGZgJoAh4GGgZmAhoGFgZmAhYGEgZmAhIGDQZkAhIGZAJmAg0GCQZkAgkGBQZiAgkGYgJkAgUGAQZiAgEG/QVgAgEGYAJiAv0F+QVgAvkF9QVeAvkFXgJgAvUF8QVeAvEF7QVeAu0F6QVcAu0FXAJeAukF5QVcAuUF4QVaAuUFWgJcAuEF3QVaAt0F2QVaAtkF6AZYAtkFWAJaAusF5wVyB+sFcgd0B+wE7QRYB+wEWAdWB7cEugQkB7cEJAchB4EEgwTvBoEE7wbtBu0E7wRaB+0EWgdYB7gEuwQmB7gEJgcjB4MEhQTxBoME8QbvBu8E8QRcB+8EXAdaB7sEvQQoB7sEKAcmB4UEhwTzBoUE8wbxBvME9QRgB/MEYAddB70EwAQqB70EKgcoB4cEiQT1BocE9QbzBvUE9wRiB/UEYgdgB8AEwgQsB8AELAcqB4kEiwT3BokE9wb1BvcE+ARkB/cEZAdiB8IExAQuB8IELgcsB4sEjQT5BosE+Qb3BvgE+gRmB/gEZgdkB8QExgQwB8QEMAcuB40EjwT7Bo0E+wb5BvoE/ARoB/oEaAdmB8YEyAQyB8YEMgcwB48EkQT9Bo8E/Qb7BvwE/gRqB/wEagdoB8gEygQ0B8gENAcyB5EEkwT/BpEE/wb9BgAFAgVtBwAFbQdrB8oEzAQ2B8oENgc0B5MElQQBB5MEAQf/BgIFBAVvBwIFbwdtB8wEzgQ4B8wEOAc2B5UElwQDB5UEAwcBBwQFBQVxBwQFcQdvB84E0AQ6B84EOgc4B5cEmQQFB5cEBQcDBwUFBwVzBwUFcwdxB9AE0gQ8B9AEPAc6B5kEmwQHB5kEBwcFBwcFCQV1BwcFdQdzB9IE1AQ+B9IEPgc8B5sEnQQJB5sECQcHBwkFfwTrBgkF6wZ1B9QE1gRAB9QEQAc+B50EnwQLB50ECwcJB9YE2ARCB9YEQgdAB58EoQQNB58EDQcLB9gE2gREB9gERAdCB6EEowQPB6EEDwcNB9oE3ARGB9oERgdEB6MEpQQRB6MEEQcPB9wE3gRIB9wESAdGB6UEqAQTB6UEEwcRB94E4ARKB94ESgdIB6gEqgQVB6gEFQcTB+AE4gRMB+AETAdKB6oErQQYB6oEGAcVB+IE5AROB+IETgdMB6sErgQZB6sEGQcXB+QE5gRQB+QEUAdOB64EsAQbB64EGwcZB+YE6ARSB+YEUgdQB7AEswQdB7AEHQcbB+gE6gRUB+gEVAdSB7MEtQQfB7MEHwcdB+oE7ARWB+oEVgdUB7UEtwQhB7UEIQcfB38EgQTtBn8E7QbrBucF4wVwB+cFcAdyB+MF3wVuB+MFbgdwB98F2wVsB98FbAduB9sF1wVpB9sFaQdsB9cF5gZnB9cFZwdpB+YG4gZlB+YGZQdnB+IG3gZjB+IGYwdlB94G2QZhB94GYQdjB9kG1QZfB9kGXwdhB9UG0AZeB9UGXgdfB9AGzQZbB9AGWwdeB80GygZZB80GWQdbB8oGxwZXB8oGVwdZB8cGwwZVB8cGVQdXB8MGvwZTB8MGUwdVB78GuwZRB78GUQdTB7sGtwZPB7sGTwdRB7cGswZNB7cGTQdPB7MGrwZLB7MGSwdNB68GqwZJB68GSQdLB6sGpwZHB6sGRwdJB6cGowZFB6cGRQdHB6MGnwZDB6MGQwdFB58GmwZBB58GQQdDB5sGlwY/B5sGPwdBB5cGkwY9B5cGPQc/B5MGjwY7B5MGOwc9B48GiwY5B48GOQc7B4sGhwY3B4sGNwc5B4cGgwY1B4cGNQc3B4MGfwYzB4MGMwc1B38GewYxB38GMQczB3sGdwYvB3sGLwcxB3cGcwYtB3cGLQcvB3MGbwYrB3MGKwctB28GawYpB28GKQcrB2sGZwYnB2sGJwcpB2cGYwYlB2cGJQcnB2MGXwYiB2MGIgclB18GWwYgB18GIAciB1sGVwYeB1sGHgcgB1cGUwYcB1cGHAceB1MGTwYaB1MGGgccB08GSgYWB08GFgcaB0oGRQYUB0oGFAcWB0UGQAYSB0UGEgcUB0AGPAYQB0AGEAcSBzwGOAYOBzwGDgcQBzgGNAYMBzgGDAcOBzQGMAYKBzQGCgcMBzAGLAYIBzAGCAcKBywGKAYGBywGBgcIBygGJAYEBygGBAcGByQGHwYCByQGAgcEBx8GGwYABx8GAAcCBxsGFwb+BhsG/gYABxcGEwb8BhcG/Ab+BhMGDwb6BhMG+gb8Bg8GCwb4Bg8G+Ab6BgsGBwb2BgsG9gb4BgcGAwb0BgcG9Ab2BgMG/wXyBgMG8gb0Bv8F+wXwBv8F8AbyBvsF9wXuBvsF7gbwBvcF8wXsBvcF7AbuBvMF7wXqBvMF6gbsBu8F6wV0B+8FdAfqBuMG5wbYBdgF3AXgBeAF5AXoBegF7AXwBfAF9AX4BfgF/AUABgAGBAYIBggGDAYQBhAGFAYYBhgGHAYgBiAGJQYpBikGLQYxBjEGNQY5BjkGPgZDBkMGRwZLBksGTgZSBlIGVgZaBloGXgZiBmIGZgZqBmoGbgZyBnIGdgZ6BnoGfgaCBoIGhgaKBooGjgaSBpIGlgaaBpoGngaiBqIGpgaqBqoGrgayBrIGtga6BroGvgbCBsIGxAbIBsgGzAbRBtEG1gbaBtoG3wbjBuMG2AXgBeAF6AXwBfAF+AUABgAGCAYQBhAGGAYgBiAGKQYxBjEGOQZDBkMGSwZSBlIGWgZiBmIGagZyBnIGegaCBoIGigaSBpIGmgaiBqIGqgayBrIGugbCBsIGyAbRBtEG2gbjBuMG4AXwBfAFAAYQBhAGIAYxBjEGQwZSBlIGYgZyBnIGggaSBpIGogayBrIGwgbRBtEG4wbwBfAFEAYxBjEGUgZyBnIGkgayBrIG0QbwBfAFMQZyBvAFcgayBg==" - } - ] -} +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v3.6.28", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Circle" + } + ], + "materials":[ + { + "doubleSided":true, + "name":"Material", + "pbrMetallicRoughness":{ + "baseColorFactor":[ + 0.011087078601121902, + 0.011087078601121902, + 0.011087078601121902, + 1 + ], + "metallicFactor":0, + "roughnessFactor":0.4000000059604645 + } + } + ], + "meshes":[ + { + "name":"Circle", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3, + "material":0 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":1910, + "max":[ + 0.29999983310699463, + 0.30012279748916626, + 0.6709707379341125 + ], + "min":[ + -0.30000022053718567, + -0.2998772859573364, + -0.3290294408798218 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":1910, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":1910, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":6084, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":22920, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":22920, + "byteOffset":22920, + "target":34962 + }, + { + "buffer":0, + "byteLength":15280, + "byteOffset":45840, + "target":34962 + }, + { + "buffer":0, + "byteLength":12168, + "byteOffset":61120, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":73288, + "uri":"data:application/octet-stream;base64,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WQ08PUrllz6Idqi+qs65PW+skz4Sdai+qs65PW+skz4Sdai+px/xPUeJjj4Zdai+px/xPUeJjj4Zdai+px/xPUeJjj4Zdai+zDcVPoSYgz7DQpG+zDcVPoSYgz7DQpG+HKMvPlDfcj41dX2+HKMvPlDfcj41dX2+uVFEPuzPYj4YE2G+uVFEPuzPYj4YE2G+q1BYPjI1Uz5iZka+q1BYPjI1Uz5iZka+0OphPu+USj7UlTu+0OphPu+USj7UlTu+P5thPkDNNz6LXha9NtZqPqY2LD6NXha9Rc1zPlypHz6SXha95CCBPtvQBz6UXha9sTSHPs/23D2YXha9mCWMPpdgpj2bXha9xpiPPotBXz2dXha99qCRPpsz5jydXha9alqSPhSJDrmeXha9FJqRPmFl6LydXha9pouPPt5KYL2VXha9hxKMPpvYpr2TXha9LhyHPoVe3b2QXha99QOBPhj7B76EXha9Yo1zPpLHH76CXha99pNqPtdNLL5+Xha9V1dhPq7dN757Xha9AjtYPo4uQr55Xha9bqlPPtELS754Xha9Va89PvFvW75yXha9kJwpPnDUar5rXha9NocOPlete75lXha9A8/gPYMHhb5eXha9fAOtPX6kib5WXha98SwwPbhwjr5MXha968iqs9wUkL4/Xha9FS0wvbdwjr4yXha9jQOtvX6kib43Xha9Fc/gvYMHhb4wXha9RIcOvk+te74oXha9nZwpvmnUar4iXha9Xq89vu5vW74cXha9e6lPvssLS74WXha9EztYvoMuQr4WXha9YVdhvq7dN74TXha9/pNqvtRNLL4QXha9a41zvovHH74MXha9+gOBvg/7B74JXha9MhyHvm5e3b0OXha9jBKMvoPYpr0LXha9p4uPvrpKYL0IXha9FZqRvgpl6LwQXha9a1qSvqdrDrkQXha9+KCRvs8z5jwQXha9x5iPvqNBXz0QXha9mSWMvp5gpj0TXha9sTSHvs723D0WXha95SCBvt3QBz4ZXha9Ts1zvl+pHz4cXha9PtZqvqQ2LD4fXha9RpthvkPNNz4iXha99H9YvmwkQj4lXha93e5PvkYHSz4mXha9VPQ9vm52Wz4zXha9ld4pvojmaj4wXha9BcIOvmTNez44Xha9tC7hveYdhT5AXha9m0+tveK+iT5HXha9qn0wvWWPjj5SXha9wG8KMA01kD5fXha9nX0wPWWPjj5rXha9kE+tPeK+iT52Xha9ti7hPeUdhT59Xha9AsIOPmLNez6FXha9kN4pPormaj6OXha9TvQ9Pm52Wz6KXha92+5PPkMHSz6HXha98H9YPmckQj6IXha9QJthPkDNNz43efm8QJthPkDNNz43efm8N9ZqPqY2LD46efm8N9ZqPqY2LD46efm8R81zPlypHz5Aefm8R81zPlypHz5Aefm85SCBPtvQBz5Hefm85SCBPtvQBz5Hefm8sjSHPs/23D1Oefm8sjSHPs/23D1Oefm8mSWMPpdgpj1Uefm8mSWMPpdgpj1Uefm8x5iPPotBXz1Yefm8x5iPPotBXz1Yefm896CRPp0z5jxKefm896CRPp0z5jxKefm8alqSPrKIDrlKefm8alqSPrKIDrlKefm8FZqRPmBl6LxKefm8FZqRPmBl6LxKefm8pouPPt5KYL04efm8pouPPt5KYL04efm8iBKMPpvYpr00efm8iBKMPpvYpr00efm8LxyHPoVe3b0tefm8LxyHPoVe3b0tefm89gOBPhj7B74mefm89gOBPhj7B74mefm8ZI1zPpLHH74hefm8ZI1zPpLHH74hefm895NqPtdNLL4befm895NqPtdNLL4befm8WVdhPq7dN74Vefm8WVdhPq7dN74Vefm8BDtYPo4uQr4Refm8BDtYPo4uQr4Refm8b6lPPtELS74Mefm8b6lPPtELS74Mefm8Va89PvFvW74Befm8Va89PvFvW74Befm8kJwpPnDUar74ePm8kJwpPnDUar74ePm8NocOPlete77oePm8NocOPlete77oePm8Bc/gPYMHhb7XePm8Bc/gPYMHhb7XePm8fgOtPX6kib7MePm8fgOtPX6kib7MePm88SwwPbhwjr61ePm88SwwPbhwjr61ePm8y0+cs9wUkL6bePm8y0+cs9wUkL6bePm8FS0wvbdwjr6CePm8FS0wvbdwjr6CePm8iwOtvX6kib58ePm8iwOtvX6kib58ePm8E8/gvYMHhb5xePm8E8/gvYMHhb5xePm8RIcOvk+te75fePm8RIcOvk+te75fePm8nZwpvmnUar5QePm8nZwpvmnUar5QePm8Xq89vu5vW75VePm8Xq89vu5vW75VePm8ealPvssLS75MePm8ealPvssLS75MePm8ETtYvoMuQr5HePm8ETtYvoMuQr5HePm8YFdhvq7dN75DePm8YFdhvq7dN75DePm8/ZNqvtRNLL48ePm8/ZNqvtRNLL48ePm8aY1zvovHH743ePm8aY1zvovHH743ePm8+QOBvg/7B74wePm8+QOBvg/7B74wePm8MhyHvm5e3b0pePm8MhyHvm5e3b0pePm8ixKMvoPYpr0kePm8ixKMvoPYpr0kePm8pouPvrpKYL0gePm8pouPvrpKYL0gePm8FZqRvgll6LwuePm8FZqRvgll6LwuePm8alqSvkNrDrkuePm8alqSvkNrDrkuePm896CRvtEz5jwuePm896CRvtEz5jwuePm8x5iPvqNBXz0/ePm8x5iPvqNBXz0/ePm8mCWMvp5gpj1CePm8mCWMvp5gpj1CePm8sDSHvs723D1JePm8sDSHvs723D1JePm85CCBvt3QBz5QePm85CCBvt3QBz5QePm8TM1zvl+pHz5XePm8TM1zvl+pHz5XePm8PdZqvqQ2LD5dePm8PdZqvqQ2LD5dePm8RJthvkPNNz5gePm8RJthvkPNNz5gePm8839YvmwkQj5mePm8839YvmwkQj5mePm83O5PvkYHSz5pePm83O5PvkYHSz5pePm8VPQ9vm52Wz51ePm8VPQ9vm52Wz51ePm8ld4pvojmaj6AePm8ld4pvojmaj6AePm8BcIOvmTNez6OePm8BcIOvmTNez6OePm8si7hveYdhT6gePm8si7hveYdhT6gePm8mU+tveK+iT6sePm8mU+tveK+iT6sePm8qn0wvWWPjj7BePm8qn0wvWWPjj7BePm8+t/4MQ01kD7cePm8+t/4MQ01kD7cePm8nX0wPWWPjj70ePm8nX0wPWWPjj70ePm8kk+tPeK+iT77ePm8kk+tPeK+iT77ePm8uC7hPeUdhT4Hefm8uC7hPeUdhT4Hefm8AsIOPmLNez4Xefm8AsIOPmLNez4Xefm8kN4pPormaj4nefm8kN4pPormaj4nefm8TvQ9Pm52Wz4hefm8TvQ9Pm52Wz4hefm83O5PPkMHSz4uefm83O5PPkMHSz4uefm88n9YPmckQj4xefm88n9YPmckQj4xefm8DmNEPksDID50Tki0DmNEPksDID50Tki0DmNEPksDID50Tki0DmNEPksDID50Tki0+mtMPursFT7s/FC0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AACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwUAAwABAAEAPwA9AD0AOwA5ADkANwA1ADUAMwAxADEALgAsACwAKgAoACgAJgAkACQAIgAgACAAHgAcABwAGgAYABgAFgAUABQAEgAQABAADwANAA0ACwAJAAkABwAFAAUAAQA9AD0AOQA1ADUAMQAsACwAKAAkACQAIAAcABwAGAAUABQAEAANAA0ACQAFAAUAPQA1ADUALAAkACQAHAAUABQADQAFAAUANQAkACQAFAAFAFEAUwCTAFEAkwCRABsAHQBcABsAXABaAAAAAgBBAAAAQQBDADYAOAB5ADYAeQB3AB0AHwBeAB0AXgBcAAIABABFAAIARQBBADgAOgB7ADgAewB5AB8AIQBgAB8AYABeAAQABgBHAAQARwBFADoAPAB9ADoAfQB7ACEAIwBiACEAYgBgAAYACABJAAYASQBHADwAPgB/ADwAfwB9ACMAJQBkACMAZABiAAgACgBLAAgASwBJAD4AAABDAD4AQwB/ACUAJwBmACUAZgBkAAoADABNAAoATQBLACcAKQBoACcAaABmAAwADgBPAAwATwBNACkAKwBqACkAagBoAA4AEQBQAA4AUABPACsALQBsACsAbABqABEAEwBSABEAUgBQAC0ALwBuAC0AbgBsABMAFQBUABMAVABSAC8AMABxAC8AcQBuABUAFwBWABUAVgBUADAAMgBzADAAcwBxABcAGQBYABcAWABWADIANAB1ADIAdQBzABkAGwBaABkAWgBYADQANgB3ADQAdwB1AJYAmADYAJYA2ADWAG0AbwCvAG0ArwCtAFMAVQCVAFMAlQCTAG8AcACwAG8AsACvAFUAVwCXAFUAlwCVAHAAcgCyAHAAsgCwAFcAWQCZAFcAmQCXAHIAdAC0AHIAtACyAFkAWwCbAFkAmwCZAHQAdgC2AHQAtgC0AFsAXQCdAFsAnQCbAEIAQACAAEIAgACCAHYAeAC4AHYAuAC2AF0AXwCfAF0AnwCdAEAARACEAEAAhACAAHgAegC6AHgAugC4AF8AYQChAF8AoQCfAEQARgCGAEQAhgCEAHoAfAC8AHoAvAC6AGEAYwCjAGEAowChAEYASACIAEYAiACGAHwAfgC+AHwAvgC8AGMAZQClAGMApQCjAEgASgCKAEgAigCIAH4AQgCCAH4AggC+AGUAZwCnAGUApwClAEoATACMAEoAjACKAGcAaQCpAGcAqQCnAEwATgCOAEwAjgCMAGkAawCrAGkAqwCpAE4AUQCRAE4AkQCOAGsAbQCtAGsArQCrAN0A3wAfAd0AHwEdAbMAtQD1ALMA9QDzAJgAmgDaAJgA2gDYALUAtwD3ALUA9wD1AJoAnADcAJoA3ADaAIMAgQDBAIMAwQDDALcAuQD5ALcA+QD3AJwAngDeAJwA3gDcAIEAhQDFAIEAxQDBALkAuwD7ALkA+wD5AJ4AoADgAJ4A4ADeAIUAhwDHAIUAxwDFALsAvQD9ALsA/QD7AKAAogDiAKAA4gDgAIcAiQDJAIcAyQDHAL0AvwD/AL0A/wD9AKIApADkAKIA5ADiAIkAiwDLAIkAywDJAL8AgwDDAL8AwwD/AKQApgDmAKQA5gDkAIsAjQDNAIsAzQDLAKYAqADoAKYA6ADmAI0AjwDPAI0AzwDNAKgAqgDqAKgA6gDoAI8AkADQAI8A0ADPAKoArADsAKoA7ADqAJAAkgDSAJAA0gDQAKwArgDuAKwA7gDsAJIAlADUAJIA1ADSAK4AsQDxAK4A8QDuAJQAlgDWAJQA1gDUALEAswDzALEA8wDxACIBJAFkASIBZAFiAcAAxAAEAcAABAEAAfgA+gA6AfgAOgE4Ad8A4QAhAd8AIQEfAcQAxgAGAcQABgEEAfoA/AA8AfoAPAE6AeEA4wAjAeEAIwEhAcYAyAAIAcYACAEGAfwA/gA+AfwAPgE8AeMA5QAlAeMAJQEjAcgAygAKAcgACgEIAf4AwgACAf4AAgE+AeUA5wAnAeUAJwElAcoAzAAMAcoADAEKAecA6QApAecAKQEnAcwAzgAOAcwADgEMAekA6wArAekAKwEpAc4A0QARAc4AEQEOAesA7QAtAesALQErAdEA0wATAdEAEwERAe0A7wAvAe0ALwEtAdMA1QAVAdMAFQETAe8A8AAwAe8AMAEvAdUA1wAXAdUAFwEVAfAA8gAyAfAAMgEwAdcA2QAZAdcAGQEXAfIA9AA0AfIANAEyAdkA2wAbAdkAGwEZAfQA9gA2AfQANgE0AdsA3QAdAdsAHQEbAcIAwAAAAcIAAAECAfYA+AA4AfYAOAE2AVEBUwGJAVEBiQGIAQkBCwFLAQkBSwFJAT8BAwFDAT8BQwF/ASQBJgFmASQBZgFkAQsBDQFNAQsBTQFLASYBKAFoASYBaAFmAQ0BDwFPAQ0BTwFNASgBKgFqASgBagFoAQ8BEAFQAQ8BUAFPASoBLAFsASoBbAFqARABEgFSARABUgFQASwBLgFuASwBbgFsARIBFAFUARIBVAFSAS4BMQFxAS4BcQFuARQBFgFWARQBVgFUATEBMwFzATEBcwFxARYBGAFYARYBWAFWATMBNQF1ATMBdQFzARgBGgFaARgBWgFYATUBNwF3ATUBdwF1ARoBHAFcARoBXAFaAQMBAQFBAQMBQQFDATcBOQF5ATcBeQF3ARwBHgFeARwBXgFcAQEBBQFFAQEBRQFBATkBOwF7ATkBewF5AR4BIAFgAR4BYAFeAQUBBwFHAQUBRwFFATsBPQF9ATsBfQF7ASABIgFiASABYgFgAQcBCQFJAQcBSQFHAT0BPwF/AT0BfwF9AYsBjAGsAYsBrAGrAW0BbwGXAW0BlwGWAVMBVQGKAVMBigGJAW8BcAGYAW8BmAGXAVUBVwGLAVUBiwGKAXABcgGZAXABmQGYAVcBWQGMAVcBjAGLAXIBdAGaAXIBmgGZAVkBWwGNAVkBjQGMAXQBdgGbAXQBmwGaAVsBXQGOAVsBjgGNAUIBQAGAAUIBgAGBAXYBeAGcAXYBnAGbAV0BXwGPAV0BjwGOAUABRAGCAUABggGAAXgBegGdAXgBnQGcAV8BYQGQAV8BkAGPAUQBRgGDAUQBgwGCAXoBfAGeAXoBngGdAWEBYwGRAWEBkQGQAUYBSAGEAUYBhAGDAXwBfgGfAXwBnwGeAWMBZQGSAWMBkgGRAUgBSgGFAUgBhQGEAX4BQgGBAX4BgQGfAWUBZwGTAWUBkwGSAUoBTAGGAUoBhgGFAWcBaQGUAWcBlAGTAUwBTgGHAUwBhwGGAWkBawGVAWkBlQGUAU4BUQGIAU4BiAGHAWsBbQGWAWsBlgGVAZkBmgG6AZkBugG5AYwBjQGtAYwBrQGsAZoBmwG7AZoBuwG6AY0BjgGuAY0BrgGtAYEBgAGgAYEBoAGhAZsBnAG8AZsBvAG7AY4BjwGvAY4BrwGuAYABggGiAYABogGgAZwBnQG9AZwBvQG8AY8BkAGwAY8BsAGvAYIBgwGjAYIBowGiAZ0BngG+AZ0BvgG9AZABkQGxAZABsQGwAYMBhAGkAYMBpAGjAZ4BnwG/AZ4BvwG+AZEBkgGyAZEBsgGxAYQBhQGlAYQBpQGkAZ8BgQGhAZ8BoQG/AZIBkwGzAZIBswGyAYUBhgGmAYUBpgGlAZMBlAG0AZMBtAGzAYYBhwGnAYYBpwGmAZQBlQG1AZQBtQG0AYcBiAGoAYcBqAGnAZUBlgG2AZUBtgG1AYgBiQGpAYgBqQGoAZYBlwG3AZYBtwG2AYkBigGqAYkBqgGpAZcBmAG4AZcBuAG3AYoBiwGrAYoBqwGqAZgBmQG5AZgBuQG4AcUBxwEHAsUBBwIFAqIBowHGAaIBxgHEAaMBpAHIAaMByAHGAYMCgQJMAoMCTAJKAvsB/QE9AvsBPQI7AuAB4gEiAuABIgIgAscByQEJAscBCQIHAv0B/wE/Av0BPwI9AuIB5AEkAuIBJAIiAskBywELAskBCwIJAv8BwwEDAv8BAwI/AuQB5gEmAuQBJgIkAssBzQENAssBDQILAuYB6AEoAuYBKAImAs0BzwEPAs0BDwINAugB6gEqAugBKgIoAs8B0AEQAs8BEAIPAuoB7AEsAuoBLAIqAtAB0gESAtABEgIQAuwB7gEuAuwBLgIsAtIB1AEUAtIBFAISAu4B8QExAu4BMQIuAtQB1gEWAtQBFgIUAvEB8wEzAvEBMwIxAtYB2AEYAtYBGAIWAvMB9QE1AvMBNQIzAtgB2gEaAtgBGgIYAvUB9wE3AvUBNwI1AtoB3AEcAtoBHAIaAsMBwQEBAsMBAQIDAvcB+QE5AvcBOQI3AtwB3gEeAtwBHgIcAsEBxQEFAsEBBQIBAvkB+wE7AvkBOwI5At4B4AEgAt4BIAIeAuQG4QZYAowCigJoAowCaAJmAoECkQJOAoECTgJMAooClgJqAooCagJoApECmgJRApECUQJOApYCngJsApYCbAJqApoCogJTApoCUwJRAp4CpgJuAp4CbgJsAqICqgJVAqICVQJTAqYCrQJwAqYCcAJuAqoCsgJXAqoCVwJVAq0CtQJxAq0CcQJwArICugJZArICWQJXArUCvQJzArUCcwJxAroCwgJbAroCWwJZAr0CxQJ1Ar0CdQJzAsICygJdAsICXQJbAs8CzQJAAs8CQAJCAsUC1QJ3AsUCdwJ1AsoC2gJfAsoCXwJdAs0C3QJEAs0CRAJAAtUC4QJ5AtUCeQJ3AtoC5gJhAtoCYQJfAt0C6QJGAt0CRgJEAuEC7QJ7AuECewJ5AuYC8gJjAuYCYwJhAukC9QJIAukCSAJGAu0C+QJ9Au0CfQJ7AvIC/gJlAvICZQJjAvUCgwJKAvUCSgJIAvkCzwJCAvkCQgJ9Av4CjAJmAv4CZgJlAiUCJwKOAiUCjgL8AqkCoQKhA6kCoQOpAz4CAgLRAj4C0QL3AikDMQOvAykDrwOnAwgCCgKFAggChQLzAp8CpwItBJ8CLQQxBCMCJQL8AiMC/ALwAi8DJwNTBC8DUwRXBDwCPgL3AjwC9wLrAq4CpQKlA64CpQOuAwYCCALzAgYC8wLnAiUDLgOsAyUDrAOjAyECIwLwAiEC8ALkAqMCrAIsBKMCLAQvBDoCPALrAjoC6wLfAiwDIwNRBCwDUQRWBAQCBgLnAgQC5wLbArECqQKpA7ECqQOxAx8CIQLkAh8C5ALYAiEDKQOnAyEDpwOfAzgCOgLfAjgC3wLTAqcCrwIpBKcCKQQtBAACBALbAgAC2wLLAicDHwNPBCcDTwRTBB0CHwLYAh0C2ALIArYCrgKuA7YCrgO2AzYCOALTAjYC0wLDAh0DJQOjAx0DowObAwICAALLAgICywLRAqwCtAIoBKwCKAQsBBsCHQLIAhsCyALAAiMDGwNNBCMDTQRRBDQCNgLDAjQCwwK7ArkCsQKxA7kCsQO5AxkCGwLAAhkCwAK4AhkDIQOfAxkDnwOXAzICNAK7AjICuwKzAq8CtwIlBK8CJQQpBBcCGQK4AhcCuAKwAh8DFwNLBB8DSwRPBDACMgKzAjACswKrAr4CtgK2A74CtgO+AxUCFwKwAhUCsAKoAn0DCwNFBH0DRQT7Ay8CMAKrAi8CqwKkAhUDHQObAxUDmwOTAxMCFQKoAhMCqAKgArQCvAIkBLQCJAQoBC0CLwKkAi0CpAKcAg0DewN9BA0DfQSLAxECEwKgAhECoAKYAhsDEwNJBBsDSQRNBCsCLQKcAisCnAKUAsECuQK5A8ECuQPBAw4CEQKYAg4CmAKPAnoDUANoBHoDaAT4AykCKwKUAikClAKIAhIDGQOXAxIDlwOQAwwCDgKPAgwCjwJ/ArcCvwIhBLcCIQQlBCcCKQKIAicCiAKOAlIDeAN8BFIDfATQAwoCDAJ/AgoCfwKFAhcDEANIBBcDSARLBMYCvgK+A8YCvgPGAwUD/wIBAwUDAQMDA3YDBANCBHYDQgT0Aw4DCAMKAw4DCgMMAwkDFQOTAwkDkwOHA/8CDwMRA/8CEQMBA7wCxAIgBLwCIAQkBAgDFAMWAwgDFgMKAwYDdAN6BAYDegSEAw8DGAMaAw8DGgMRAxMDBwNDBBMDQwRJBBQDHAMeAxQDHgMWA8kCwQLBA8kCwQPJAxgDIAMiAxgDIgMaA3EDfQP7A3ED+wPvAxwDJAMmAxwDJgMeAwIDEgOQAwIDkAOAAyADKAMqAyADKgMiA78CxwIdBL8CHQQhBCQDKwMtAyQDLQMmA3sDbwN3BHsDdwR9BCgDMAMyAygDMgMqAxADAANABBADQARIBCsDMwM1AysDNQMtA84C0AIGBM4CBgTOAzADOAM6AzADOgMyA24DegP4A24D+APsAzMDOwM9AzMDPQM1AwsDCQOHAwsDhwNFBDgDQANCAzgDQgM6A9ICzAIcBNICHATSAzsDQwNFAzsDRQM9A3gDbAN2BHgDdgR8BEADSANKA0ADSgNCAwcDDQOLAwcDiwNDBFEDSwNNA1EDTQNPA9YCxgLGA9YCxgPWA0MDUwNVA0MDVQNFA2oDdgP0A2oD9APoA0gDWANaA0gDWgNKAwQDAgOAAwQDgANCBEsDWwNdA0sDXQNNA8QC1AIaBMQCGgQgBFMDXwNhA1MDYQNVA3QDaAN0BHQDdAR6BFgDZANmA1gDZgNaAwADBgOEAwADhANABFsDZwNpA1sDaQNdA9kCyQLJA9kCyQPZA18DawNtA18DbQNhA2UDcQPvA2UD7wPjA2QDcANyA2QDcgNmA8cC1wIXBMcCFwQdBGcDcwN1A2cDdQNpA28DYwNxBG8DcQR3BGsDdwN5A2sDeQNtA94CzgLOA94CzgPeA3ADfAN+A3ADfgNyA2IDbgPsA2ID7APgA3MDBQMDA3MDAwN1A8wC3AIWBMwCFgQcBHcDUQNPA3cDTwN5A2wDYANwBGwDcAR2BHwDDgMMA3wDDAN+A/wDRgQCBPwDAgT+A/cDZwQFBPcDBQT5A/MDQQQJBPMDCQT1A/AD/AP+A/AD/gPyA+sD9wP5A+sD+QPtA+cD8wP1A+cD9QPpA+QD8APyA+QD8gPmA98D6wPtA98D7QPhA9sD5wPpA9sD6QPdA9gD5APmA9gD5gPaA9MD3wPhA9MD4QPVA8sD2wPdA8sD3QPNA8gD2APaA8gD2gPKA8MD0wPVA8MD1QPFA2cEywPNA2cEzQMFBMADyAPKA8ADygPCA7sDwwPFA7sDxQO9A7gDwAPCA7gDwgO6A7MDuwO9A7MDvQO1A7ADuAO6A7ADugOyA6sDswO1A6sDtQOtA6gDsAOyA6gDsgOqA6QDqwOtA6QDrQOmA6ADqAOqA6ADqgOiA5wDpAOmA5wDpgOeA5gDoAOiA5gDogOaA5QDnAOeA5QDngOWA48DmAOaA48DmgORA4gDlAOWA4gDlgOKA38DjwORA38DkQOBA0YEiAOKA0YEigMCBEEEfwOBA0EEgQMJBIUDPQQ/BIUDPwSDA44DPAREBI4DRASMAz0EOQRHBD0ERwQ/BDwEOARKBDwESgREBDkENgRMBDkETARHBDgENAROBDgETgRKBDYEMgRQBDYEUARMBDQEMARSBDQEUgROBDIELgRUBDIEVARQBDAEKwRVBDAEVQRSBC4EKgRYBC4EWARUBCsEJwRZBCsEWQRVBCoEJgRcBCoEXARYBCcEIwRdBCcEXQRZBCYEIgRgBCYEYARcBCMEHwRhBCMEYQRdBCIEHgRkBCIEZARgBNEDGwRlBNEDZQTPAx8EGQRpBB8EaQRhBB4EGARsBB4EbARkBBsEFQRtBBsEbQRlBBkEEwRvBBkEbwRpBBgEEgRyBBgEcgRsBBUEDwRzBBUEcwRtBBMEDQR1BBMEdQRvBBIEDAR4BBIEeARyBA8EBwR5BA8EeQRzBA0EAwR7BA0EewR1BAwEAAR+BAwEfgR4BAcEhQODAwcEgwN5BAME0QPPAwMEzwN7BAAEjgOMAwAEjAN+BDQDLANWBDQDVgRaBJsCowIvBJsCLwQzBC4DNgO0Ay4DtAOsA6UCnQKdA6UCnQOlAzcDLwNXBDcDVwRbBJcCnwIxBJcCMQQ1BDEDOQO3AzEDtwOvA6ECmQKZA6ECmQOhAzwDNANaBDwDWgReBPsCjQKNA/sCjQP/A5MCmwIzBJMCMwQ3BDYDPgO8AzYDvAO0A4sC/QL9A4sC/QMBBJ0ClQKVA50ClQOdAz8DNwNbBD8DWwRfBPgC0gLSA/gC0gMEBJAClwI1BJACNQQ6BDkDQQO/AzkDvwO3A9AC+gL6A9AC+gMGBJkCkgKSA5kCkgOZA0QDPANeBEQDXgRiBPQChgKGA/QChgMIBIcCkwI3BIcCNwQ7BD4DRgPEAz4DxAO8A4QC9gL2A4QC9gMKBJUCiQKJA5UCiQOVA0cDPwNfBEcDXwRjBO8C+wL/A+8C/wMLBIACkAI6BIACOgQ+BEEDSQPHA0EDxwO/A/0C8QLxA/0C8QP9A5ICggKCA5ICggOSA0wDUgPQA0wD0ANmBOwC+AIEBOwCBAQOBI0ChwI7BI0COwSNA1ADTgPMA1ADzANoBPoC7gLuA/oC7gP6A4kCiwIBBIkCAQSJA1QDRANiBFQDYgRqBOgC9AIIBOgCCAQQBIYCgAI+BIYCPgSGA0YDVgPUA0YD1APEA/YC6gLqA/YC6gP2A4IChAIKBIICCgSCA1cDRwNjBFcDYwRrBOMC7wILBOMCCwQRBEkDWQPXA0kD1wPHA/EC5QLlA/EC5QPxA1wDTANmBFwDZgRuBOAC7AIOBOACDgQUBE4DXgPcA04D3APMA+4C4gLiA+4C4gPuA2ADVANqBGADagRwBNwC6AIQBNwCEAQWBFYDYgPgA1YD4APUA+oC3gLeA+oC3gPqA2MDVwNrBGMDawRxBNcC4wIRBNcCEQQXBFkDZQPjA1kD4wPXA+UC2QLZA+UC2QPlA2gDXANuBGgDbgR0BNQC4AIUBNQCFAQaBF4DagPoA14D6APcA+IC1gLWA+IC1gPiA6QBpQHKAaQBygHIAaUBpgHMAaUBzAHKAaYBpwHOAaYBzgHMAacBqAHRAacB0QHOAagBqQHTAagB0wHRAakBqgHVAakB1QHTAaoBqwHXAaoB1wHVAasBrAHZAasB2QHXAawBrQHbAawB2wHZAa0BrgHdAa0B3QHbAa4BrwHfAa4B3wHdAa8BsAHhAa8B4QHfAbABsQHjAbAB4wHhAbEBsgHlAbEB5QHjAbIBswHnAbIB5wHlAbMBtAHpAbMB6QHnAbQBtQHrAbQB6wHpAbUBtgHtAbUB7QHrAbYBtwHvAbYB7wHtAbcBuAHwAbcB8AHvAbgBuQHyAbgB8gHwAbkBugH0AbkB9AHyAboBuwH2AboB9gH0AbsBvAH4AbsB+AH2AbwBvQH6AbwB+gH4Ab0BvgH8Ab0B/AH6Ab4BvwH+Ab4B/gH8Ab8BoQHCAb8BwgH+AaEBoAHAAaEBwAHCAaABogHEAaABxAHAAesEQAVBBesEQQXuBLYEJgUnBbYEJwW5BIIEDAUNBYIEDQWEBO4EQQVCBe4EQgXwBLkEJwUoBbkEKAW8BIQEDQUOBYQEDgWGBPAEQgVDBfAEQwXyBLwEKAUpBbwEKQW+BIYEDgUPBYYEDwWIBPIEQwVEBfIERAX0BL4EKQUqBb4EKgW/BIgEDwUQBYgEEAWKBPQERAVFBfQERQX2BL8EKgUrBb8EKwXBBIoEEAURBYoEEQWMBPYERQVGBfYERgX5BMEEKwUsBcEELAXDBIwEEQUSBYwEEgWOBPkERgVHBfkERwX7BMMELAUtBcMELQXFBI4EEgUTBY4EEwWQBPsERwVIBfsESAX9BMUELQUuBcUELgXHBJAEEwUUBZAEFAWSBP0ESAVJBf0ESQX/BMcELgUvBccELwXJBJIEFAUVBZIEFQWUBP8ESQVKBf8ESgUBBckELwUwBckEMAXLBJQEFQUWBZQEFgWWBAEFSgVLBQEFSwUDBcsEMAUxBcsEMQXNBJYEFgUXBZYEFwWYBAMFSwVMBQMFTAUGBc0EMQUyBc0EMgXPBJgEFwUYBZgEGAWaBAYFTAVNBQYFTQUIBc8EMgUzBc8EMwXRBJoEGAUZBZoEGQWcBAgFTQVOBQgFTgUKBdEEMwU0BdEENAXTBJwEGQUaBZwEGgWeBAoFTgULBQoFCwWABNMENAU1BdMENQXVBJ4EGgUbBZ4EGwWgBNUENQU2BdUENgXXBKAEGwUcBaAEHAWiBNcENgU3BdcENwXZBKIEHAUdBaIEHQWkBNkENwU4BdkEOAXbBKQEHQUeBaQEHgWmBNsEOAU5BdsEOQXdBKYEHgUfBaYEHwWnBN0EOQU6Bd0EOgXfBKcEHwUgBacEIAWpBN8EOgU7Bd8EOwXhBKkEIAUhBakEIQWsBOEEOwU8BeEEPAXjBKwEIQUiBawEIgWvBOMEPAU9BeMEPQXlBK8EIgUjBa8EIwWxBOUEPQU+BeUEPgXnBLEEIwUkBbEEJAWyBOcEPgU/BecEPwXpBLIEJAUlBbIEJQW0BOkEPwVABekEQAXrBLQEJQUmBbQEJgW2BIAECwUMBYAEDAWCBD8FtwW5BT8FuQVABSUFgwWFBSUFhQUmBQsFUAVSBQsFUgUMBUAFuQW7BUAFuwVBBSYFhQWHBSYFhwUnBQwFUgVUBQwFVAUNBUEFuwW9BUEFvQVCBScFhwWJBScFiQUoBQ0FVAVWBQ0FVgUOBUIFvQW/BUIFvwVDBSgFiQWLBSgFiwUpBQ4FVgVYBQ4FWAUPBUMFvwXBBUMFwQVEBSkFiwWNBSkFjQUqBQ8FWAVaBQ8FWgUQBUQFwQXDBUQFwwVFBSoFjQWPBSoFjwUrBRAFWgVcBRAFXAURBUUFwwXGBUUFxgVGBSsFjwWRBSsFkQUsBREFXAVeBREFXgUSBUYFxgXIBUYFyAVHBSwFkQWTBSwFkwUtBRIFXgVgBRIFYAUTBUcFyAXKBUcFygVIBS0FkwWVBS0FlQUuBRMFYAViBRMFYgUUBUgFygXMBUgFzAVJBS4FlQWXBS4FlwUvBRQFYgVkBRQFZAUVBUkFzAXOBUkFzgVKBS8FlwWZBS8FmQUwBRUFZAVmBRUFZgUWBUoFzgXQBUoF0AVLBTAFmQWbBTAFmwUxBRYFZgVoBRYFaAUXBUsF0AXSBUsF0gVMBTEFmwWdBTEFnQUyBRcFaAVqBRcFagUYBUwF0gXUBUwF1AVNBTIFnQWfBTIFnwUzBRgFagVsBRgFbAUZBU0F1AXWBU0F1gVOBTMFnwWhBTMFoQU0BRkFbAVuBRkFbgUaBU4F1gVQBU4FUAULBTQFoQWjBTQFowU1BRoFbgVwBRoFcAUbBTUFowWlBTUFpQU2BRsFcAVyBRsFcgUcBTYFpQWnBTYFpwU3BRwFcgV0BRwFdAUdBTcFpwWpBTcFqQU4BR0FdAV2BR0FdgUeBTgFqQWrBTgFqwU5BR4FdgV4BR4FeAUfBTkFqwWtBTkFrQU6BR8FeAV6BR8FegUgBToFrQWvBToFrwU7BSAFegV8BSAFfAUhBTsFrwWxBTsFsQU8BSEFfAV+BSEFfgUiBTwFsQWzBTwFswU9BSIFfgWABSIFgAUjBT0FswW1BT0FtQU+BSMFgAWBBSMFgQUkBT4FtQW3BT4FtwU/BSQFgQWDBSQFgwUlBa4FlAaYBq4FmAawBXkFLgYzBnkFMwZ7BbAFmAacBrAFnAayBXsFMwY3BnsFNwZ9BbIFnAagBrIFoAa0BX0FNwY7Bn0FOwZ/BbQFoAakBrQFpAa2BX8FOwY9Bn8FPQaCBbYFpAaoBrYFqAa4BYIFPQZBBoIFQQaEBbgFqAasBrgFrAa6BYQFQQZEBoQFRAaGBU8F2gXeBU8F3gVRBboFrAawBroFsAa8BYYFRAZIBoYFSAaIBVEF3gXiBVEF4gVTBbwFsAa0BrwFtAa+BYgFSAZMBogFTAaKBVMF4gXmBVMF5gVVBb4FtAa4Br4FuAbABYoFTAZQBooFUAaMBVUF5gXqBVUF6gVXBcAFuAa8BsAFvAbCBYwFUAZUBowFVAaOBVcF6gXuBVcF7gVZBcIFvAbABsIFwAbEBY4FVAZYBo4FWAaQBVkF7gXyBVkF8gVbBcQFwAbFBsQFxQbFBZAFWAZcBpAFXAaSBVsF8gX2BVsF9gVdBcUFxQbJBsUFyQbHBZIFXAZgBpIFYAaUBV0F9gX6BV0F+gVfBccFyQbOBscFzgbJBZQFYAZkBpQFZAaWBV8F+gX+BV8F/gVhBckFzgbSBskF0gbLBZYFZAZoBpYFaAaYBWEF/gUCBmEFAgZjBcsF0gbXBssF1wbNBZgFaAZsBpgFbAaaBWMFAgYGBmMFBgZlBc0F1wbbBs0F2wbPBZoFbAZwBpoFcAacBWUFBgYKBmUFCgZnBc8F2wbgBs8F4AbRBZwFcAZ0BpwFdAaeBWcFCgYOBmcFDgZpBdEF4AblBtEF5QbTBZ4FdAZ4Bp4FeAagBWkFDgYRBmkFEQZrBdMF5QbpBtMF6QbVBaAFeAZ8BqAFfAaiBWsFEQYVBmsFFQZtBdUF6QbaBdUF2gVPBaIFfAaABqIFgAakBW0FFQYZBm0FGQZvBaQFgAaEBqQFhAamBW8FGQYdBm8FHQZxBaYFhAaIBqYFiAaoBXEFHQYhBnEFIQZzBagFiAaMBqgFjAaqBXMFIQYmBnMFJgZ1BaoFjAaQBqoFkAasBXUFJgYqBnUFKgZ3BawFkAaUBqwFlAauBXcFKgYuBncFLgZ5BegG5AZYAuEG3AZWAuEGVgJYAt0G2AZXAtgG1AZVAtgGVQJXAtMGzwZUAs8GywZSAs8GUgJUAssGxgZQAssGUAJSAsYGwQZQAsEGvQZPAsEGTwJQAr0GuQZNAr0GTQJPArkGtQZNArUGsQZLArUGSwJNArEGrQZLAq0GqQZJAq0GSQJLAqkGpQZJAqUGoQZJAqEGnQZJAp0GmQZHAp0GRwJJApkGlQZHApUGkQZFApUGRQJHApEGjQZFAo0GiQZBAo0GQQJFAokGhQZBAoUGgQZDAoUGQwJBAoEGfQZDAn0GeQZ+An0GfgJDAnkGdQZ8AnkGfAJ+AnUGcQZ8AnEGbQZ6AnEGegJ8Am0GaQZ6AmkGZQZ4AmkGeAJ6AmUGYQZ4AmEGXQZ4Al0GWQZ4AlkGVQZ2AlkGdgJ4AlUGUQZ2AlEGTQZ0AlEGdAJ2Ak0GSQZ0AkkGRgZyAkkGcgJ0AkYGQgZvAkYGbwJyAkIGPwZvAj8GOgZtAj8GbQJvAjoGNgZrAjoGawJtAjYGMgZrAjIGLwZpAjIGaQJrAi8GKwZnAi8GZwJpAisGJwZnAicGIgZnAiMGHgZmAiMGZgJoAh4GGgZmAhoGFgZmAhYGEgZmAhIGDQZkAhIGZAJmAg0GCQZkAgkGBQZiAgkGYgJkAgUGAQZiAgEG/QVgAgEGYAJiAv0F+QVgAvkF9QVeAvkFXgJgAvUF8QVeAvEF7QVeAu0F6QVcAu0FXAJeAukF5QVcAuUF4QVaAuUFWgJcAuEF3QVaAt0F2QVaAtkF6AZYAtkFWAJaAusF5wVyB+sFcgd0B+wE7QRYB+wEWAdWB7cEugQkB7cEJAchB4EEgwTvBoEE7wbtBu0E7wRaB+0EWgdYB7gEuwQmB7gEJgcjB4MEhQTxBoME8QbvBu8E8QRcB+8EXAdaB7sEvQQoB7sEKAcmB4UEhwTzBoUE8wbxBvME9QRgB/MEYAddB70EwAQqB70EKgcoB4cEiQT1BocE9QbzBvUE9wRiB/UEYgdgB8AEwgQsB8AELAcqB4kEiwT3BokE9wb1BvcE+ARkB/cEZAdiB8IExAQuB8IELgcsB4sEjQT5BosE+Qb3BvgE+gRmB/gEZgdkB8QExgQwB8QEMAcuB40EjwT7Bo0E+wb5BvoE/ARoB/oEaAdmB8YEyAQyB8YEMgcwB48EkQT9Bo8E/Qb7BvwE/gRqB/wEagdoB8gEygQ0B8gENAcyB5EEkwT/BpEE/wb9BgAFAgVtBwAFbQdrB8oEzAQ2B8oENgc0B5MElQQBB5MEAQf/BgIFBAVvBwIFbwdtB8wEzgQ4B8wEOAc2B5UElwQDB5UEAwcBBwQFBQVxBwQFcQdvB84E0AQ6B84EOgc4B5cEmQQFB5cEBQcDBwUFBwVzBwUFcwdxB9AE0gQ8B9AEPAc6B5kEmwQHB5kEBwcFBwcFCQV1BwcFdQdzB9IE1AQ+B9IEPgc8B5sEnQQJB5sECQcHBwkFfwTrBgkF6wZ1B9QE1gRAB9QEQAc+B50EnwQLB50ECwcJB9YE2ARCB9YEQgdAB58EoQQNB58EDQcLB9gE2gREB9gERAdCB6EEowQPB6EEDwcNB9oE3ARGB9oERgdEB6MEpQQRB6MEEQcPB9wE3gRIB9wESAdGB6UEqAQTB6UEEwcRB94E4ARKB94ESgdIB6gEqgQVB6gEFQcTB+AE4gRMB+AETAdKB6oErQQYB6oEGAcVB+IE5AROB+IETgdMB6sErgQZB6sEGQcXB+QE5gRQB+QEUAdOB64EsAQbB64EGwcZB+YE6ARSB+YEUgdQB7AEswQdB7AEHQcbB+gE6gRUB+gEVAdSB7MEtQQfB7MEHwcdB+oE7ARWB+oEVgdUB7UEtwQhB7UEIQcfB38EgQTtBn8E7QbrBucF4wVwB+cFcAdyB+MF3wVuB+MFbgdwB98F2wVsB98FbAduB9sF1wVpB9sFaQdsB9cF5gZnB9cFZwdpB+YG4gZlB+YGZQdnB+IG3gZjB+IGYwdlB94G2QZhB94GYQdjB9kG1QZfB9kGXwdhB9UG0AZeB9UGXgdfB9AGzQZbB9AGWwdeB80GygZZB80GWQdbB8oGxwZXB8oGVwdZB8cGwwZVB8cGVQdXB8MGvwZTB8MGUwdVB78GuwZRB78GUQdTB7sGtwZPB7sGTwdRB7cGswZNB7cGTQdPB7MGrwZLB7MGSwdNB68GqwZJB68GSQdLB6sGpwZHB6sGRwdJB6cGowZFB6cGRQdHB6MGnwZDB6MGQwdFB58GmwZBB58GQQdDB5sGlwY/B5sGPwdBB5cGkwY9B5cGPQc/B5MGjwY7B5MGOwc9B48GiwY5B48GOQc7B4sGhwY3B4sGNwc5B4cGgwY1B4cGNQc3B4MGfwYzB4MGMwc1B38GewYxB38GMQczB3sGdwYvB3sGLwcxB3cGcwYtB3cGLQcvB3MGbwYrB3MGKwctB28GawYpB28GKQcrB2sGZwYnB2sGJwcpB2cGYwYlB2cGJQcnB2MGXwYiB2MGIgclB18GWwYgB18GIAciB1sGVwYeB1sGHgcgB1cGUwYcB1cGHAceB1MGTwYaB1MGGgccB08GSgYWB08GFgcaB0oGRQYUB0oGFAcWB0UGQAYSB0UGEgcUB0AGPAYQB0AGEAcSBzwGOAYOBzwGDgcQBzgGNAYMBzgGDAcOBzQGMAYKBzQGCgcMBzAGLAYIBzAGCAcKBywGKAYGBywGBgcIBygGJAYEBygGBAcGByQGHwYCByQGAgcEBx8GGwYABx8GAAcCBxsGFwb+BhsG/gYABxcGEwb8BhcG/Ab+BhMGDwb6BhMG+gb8Bg8GCwb4Bg8G+Ab6BgsGBwb2BgsG9gb4BgcGAwb0BgcG9Ab2BgMG/wXyBgMG8gb0Bv8F+wXwBv8F8AbyBvsF9wXuBvsF7gbwBvcF8wXsBvcF7AbuBvMF7wXqBvMF6gbsBu8F6wV0B+8FdAfqBuMG5wbYBdgF3AXgBeAF5AXoBegF7AXwBfAF9AX4BfgF/AUABgAGBAYIBggGDAYQBhAGFAYYBhgGHAYgBiAGJQYpBikGLQYxBjEGNQY5BjkGPgZDBkMGRwZLBksGTgZSBlIGVgZaBloGXgZiBmIGZgZqBmoGbgZyBnIGdgZ6BnoGfgaCBoIGhgaKBooGjgaSBpIGlgaaBpoGngaiBqIGpgaqBqoGrgayBrIGtga6BroGvgbCBsIGxAbIBsgGzAbRBtEG1gbaBtoG3wbjBuMG2AXgBeAF6AXwBfAF+AUABgAGCAYQBhAGGAYgBiAGKQYxBjEGOQZDBkMGSwZSBlIGWgZiBmIGagZyBnIGegaCBoIGigaSBpIGmgaiBqIGqgayBrIGugbCBsIGyAbRBtEG2gbjBuMG4AXwBfAFAAYQBhAGIAYxBjEGQwZSBlIGYgZyBnIGggaSBpIGogayBrIGwgbRBtEG4wbwBfAFEAYxBjEGUgZyBnIGkgayBrIG0QbwBfAFMQZyBvAFcgayBg==" + } + ] +} diff --git a/app/src/components/icons/RealTimeVisulationIcons.tsx b/app/src/components/icons/RealTimeVisulationIcons.tsx index ee978e0..228cd21 100644 --- a/app/src/components/icons/RealTimeVisulationIcons.tsx +++ b/app/src/components/icons/RealTimeVisulationIcons.tsx @@ -1,160 +1,160 @@ -export function CleanPannel() { - return ( - - - - - - - - - - - - - - - - - ); -} - -export function EyeIcon({ fill }: { fill?: string }) { - return ( - - - - - ); -} - -export function LockIcon({ fill }: { fill?: string }) { - return ( - - - - ); -} -export function StockIncreseIcon() { - return ( - - - - - - - - - - - - - - - - - - - ); -} +export function CleanPannel() { + return ( + + + + + + + + + + + + + + + + + ); +} + +export function EyeIcon({ fill }: { fill?: string }) { + return ( + + + + + ); +} + +export function LockIcon({ fill }: { fill?: string }) { + return ( + + + + ); +} +export function StockIncreseIcon() { + return ( + + + + + + + + + + + + + + + + + + + ); +} diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index a29d930..737271e 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from "react"; import Header from "./Header"; -import useModuleStore from "../../../store/useModuleStore"; +import useModuleStore, { useSubModuleStore } from "../../../store/useModuleStore"; import { AnalysisIcon, MechanicsIcon, @@ -14,15 +14,17 @@ import GlobalProperties from "./properties/GlobalProperties"; import AsstePropertiies from "./properties/AssetProperties"; import Analysis from "./analysis/Analysis"; import Simulations from "./simulation/Simulations"; +import { useSelectedActionSphere } from "../../../store/store"; const SideBarRight: React.FC = () => { const { activeModule } = useModuleStore(); - const [activeList, setActiveList] = useState("properties"); + const { selectedActionSphere } = useSelectedActionSphere(); + const { subModule, setSubModule } = useSubModuleStore(); const { toggleUI } = useToggleStore(); - // Reset activeList whenever activeModule changes + // Reset subModule whenever activeModule changes useEffect(() => { - setActiveList("properties"); + setSubModule("properties"); }, [activeModule]); return ( @@ -31,38 +33,34 @@ const SideBarRight: React.FC = () => { {toggleUI && (
setActiveList("properties")} + className={`sidebar-action-list ${subModule === "properties" ? "active" : "" + }`} + onClick={() => setSubModule("properties")} > - +
{activeModule === "simulation" && ( <>
setActiveList("mechanics")} + className={`sidebar-action-list ${subModule === "mechanics" ? "active" : "" + }`} + onClick={() => setSubModule("mechanics")} > - +
setActiveList("simulations")} + className={`sidebar-action-list ${subModule === "simulations" ? "active" : "" + }`} + onClick={() => setSubModule("simulations")} > - +
setActiveList("analysis")} + className={`sidebar-action-list ${subModule === "analysis" ? "active" : "" + }`} + onClick={() => setSubModule("analysis")} > - +
)} @@ -70,7 +68,7 @@ const SideBarRight: React.FC = () => { )} {/* process builder */} {toggleUI && - activeList === "properties" && + subModule === "properties" && activeModule !== "visualization" && (
@@ -84,21 +82,28 @@ const SideBarRight: React.FC = () => { {toggleUI && activeModule === "simulation" && ( <> - {activeList === "mechanics" && ( + {(subModule === "mechanics" && selectedActionSphere) && (
)} - {activeList === "analysis" && ( + {(subModule === "mechanics" && !selectedActionSphere) && ( +
+
+ {/* */} +
+
+ )} + {subModule === "analysis" && (
)} - {activeList === "simulations" && ( + {subModule === "simulations" && (
diff --git a/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx index 9aa27bb..85ae67a 100644 --- a/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx +++ b/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx @@ -11,8 +11,11 @@ import LabledDropdown from "../../../ui/inputs/LabledDropdown"; import RegularDropDown from "../../../ui/inputs/RegularDropDown"; import { handleResize } from "../../../../functions/handleResizePannel"; import EyeDropInput from "../../../ui/inputs/EyeDropInput"; +import { useSelectedActionSphere } from "../../../../store/store"; const MachineMechanics: React.FC = () => { + const { selectedActionSphere, setSelectedActionSphere } = useSelectedActionSphere(); + console.log('selectedActionSphere: ', selectedActionSphere); const [actionList, setActionList] = useState([]); const [triggerList, setTriggerList] = useState([]); const [selectedItem, setSelectedItem] = useState<{ @@ -68,8 +71,8 @@ const MachineMechanics: React.FC = () => { return (
-
Selected Object
-
+
{selectedActionSphere.path.modelName}
+ {/*
Process:
"} @@ -79,7 +82,7 @@ const MachineMechanics: React.FC = () => {
-
+
*/}
@@ -97,12 +100,11 @@ const MachineMechanics: React.FC = () => { {actionList.map((action, index) => (
{ {triggerList.map((trigger, index) => (
{ label="Speed" value="" activeOption=".mm" - onChange={() => {}} + onChange={() => { }} /> diff --git a/app/src/components/ui/charts/BarGraphComponent.tsx b/app/src/components/ui/charts/BarGraphComponent.tsx index 9a07473..da656f2 100644 --- a/app/src/components/ui/charts/BarGraphComponent.tsx +++ b/app/src/components/ui/charts/BarGraphComponent.tsx @@ -1,94 +1,94 @@ -import { useMemo } from "react"; - -import { Bar } from "react-chartjs-2"; - -interface ChartComponentProps { - type: any; - title: string; - fontFamily?: string; - fontSize?: string; - fontWeight?: "Light" | "Regular" | "Bold"; - data: any; -} - -const LineGraphComponent = ({ - title, - fontFamily, - fontSize, - fontWeight = "Regular", -}: ChartComponentProps) => { - // Memoize Font Weight Mapping - const chartFontWeightMap = useMemo( - () => ({ - Light: "lighter" as const, - Regular: "normal" as const, - Bold: "bold" as const, - }), - [] - ); - - // Parse and Memoize Font Size - const fontSizeValue = useMemo( - () => (fontSize ? parseInt(fontSize) : 12), - [fontSize] - ); - - // Determine and Memoize Font Weight - const fontWeightValue = useMemo( - () => chartFontWeightMap[fontWeight], - [fontWeight, chartFontWeightMap] - ); - - // Memoize Chart Font Style - const chartFontStyle = useMemo( - () => ({ - family: fontFamily || "Arial", - size: fontSizeValue, - weight: fontWeightValue, - }), - [fontFamily, fontSizeValue, fontWeightValue] - ); - - const options = useMemo( - () => ({ - responsive: true, - maintainAspectRatio: false, - plugins: { - title: { - display: true, - text: title, - font: chartFontStyle, - }, - legend: { - display: false, - }, - }, - scales: { - x: { - ticks: { - display: false, // This hides the x-axis labels - }, - }, - }, - }), - [title, chartFontStyle] - ); - - const chartData = { - labels: ["January", "February", "March", "April", "May", "June", "July"], - datasets: [ - { - label: "My First Dataset", - data: [65, 59, 80, 81, 56, 55, 40], - backgroundColor: "#6f42c1", - borderColor: "#ffffff", - borderWidth: 2, - fill: false, - }, - ], - }; - - return ; -}; - -export default LineGraphComponent; +import { useMemo } from "react"; + +import { Bar } from "react-chartjs-2"; + +interface ChartComponentProps { + type: any; + title: string; + fontFamily?: string; + fontSize?: string; + fontWeight?: "Light" | "Regular" | "Bold"; + data: any; +} + +const LineGraphComponent = ({ + title, + fontFamily, + fontSize, + fontWeight = "Regular", +}: ChartComponentProps) => { + // Memoize Font Weight Mapping + const chartFontWeightMap = useMemo( + () => ({ + Light: "lighter" as const, + Regular: "normal" as const, + Bold: "bold" as const, + }), + [] + ); + + // Parse and Memoize Font Size + const fontSizeValue = useMemo( + () => (fontSize ? parseInt(fontSize) : 12), + [fontSize] + ); + + // Determine and Memoize Font Weight + const fontWeightValue = useMemo( + () => chartFontWeightMap[fontWeight], + [fontWeight, chartFontWeightMap] + ); + + // Memoize Chart Font Style + const chartFontStyle = useMemo( + () => ({ + family: fontFamily || "Arial", + size: fontSizeValue, + weight: fontWeightValue, + }), + [fontFamily, fontSizeValue, fontWeightValue] + ); + + const options = useMemo( + () => ({ + responsive: true, + maintainAspectRatio: false, + plugins: { + title: { + display: true, + text: title, + font: chartFontStyle, + }, + legend: { + display: false, + }, + }, + scales: { + x: { + ticks: { + display: false, // This hides the x-axis labels + }, + }, + }, + }), + [title, chartFontStyle] + ); + + const chartData = { + labels: ["January", "February", "March", "April", "May", "June", "July"], + datasets: [ + { + label: "My First Dataset", + data: [65, 59, 80, 81, 56, 55, 40], + backgroundColor: "#6f42c1", + borderColor: "#ffffff", + borderWidth: 2, + fill: false, + }, + ], + }; + + return ; +}; + +export default LineGraphComponent; diff --git a/app/src/components/ui/charts/LineGraphComponent.tsx b/app/src/components/ui/charts/LineGraphComponent.tsx index cf1a47f..7f420d7 100644 --- a/app/src/components/ui/charts/LineGraphComponent.tsx +++ b/app/src/components/ui/charts/LineGraphComponent.tsx @@ -1,93 +1,93 @@ -import { useMemo } from "react"; -import { Line } from "react-chartjs-2"; - -interface ChartComponentProps { - type: any; - title: string; - fontFamily?: string; - fontSize?: string; - fontWeight?: "Light" | "Regular" | "Bold"; - data: any; -} - -const LineGraphComponent = ({ - title, - fontFamily, - fontSize, - fontWeight = "Regular", -}: ChartComponentProps) => { - // Memoize Font Weight Mapping - const chartFontWeightMap = useMemo( - () => ({ - Light: "lighter" as const, - Regular: "normal" as const, - Bold: "bold" as const, - }), - [] - ); - - // Parse and Memoize Font Size - const fontSizeValue = useMemo( - () => (fontSize ? parseInt(fontSize) : 12), - [fontSize] - ); - - // Determine and Memoize Font Weight - const fontWeightValue = useMemo( - () => chartFontWeightMap[fontWeight], - [fontWeight, chartFontWeightMap] - ); - - // Memoize Chart Font Style - const chartFontStyle = useMemo( - () => ({ - family: fontFamily || "Arial", - size: fontSizeValue, - weight: fontWeightValue, - }), - [fontFamily, fontSizeValue, fontWeightValue] - ); - - const options = useMemo( - () => ({ - responsive: true, - maintainAspectRatio: false, - plugins: { - title: { - display: true, - text: title, - font: chartFontStyle, - }, - legend: { - display: false, - }, - }, - scales: { - x: { - ticks: { - display: false, // This hides the x-axis labels - }, - }, - }, - }), - [title, chartFontStyle] - ); - - const chartData = { - labels: ["January", "February", "March", "April", "May", "June", "July"], - datasets: [ - { - label: "My First Dataset", - data: [65, 59, 80, 81, 56, 55, 40], - backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple) - borderColor: "#ffffff", // Keeping border color white - borderWidth: 2, - fill: false, - }, - ], - }; - - return ; -}; - -export default LineGraphComponent; +import { useMemo } from "react"; +import { Line } from "react-chartjs-2"; + +interface ChartComponentProps { + type: any; + title: string; + fontFamily?: string; + fontSize?: string; + fontWeight?: "Light" | "Regular" | "Bold"; + data: any; +} + +const LineGraphComponent = ({ + title, + fontFamily, + fontSize, + fontWeight = "Regular", +}: ChartComponentProps) => { + // Memoize Font Weight Mapping + const chartFontWeightMap = useMemo( + () => ({ + Light: "lighter" as const, + Regular: "normal" as const, + Bold: "bold" as const, + }), + [] + ); + + // Parse and Memoize Font Size + const fontSizeValue = useMemo( + () => (fontSize ? parseInt(fontSize) : 12), + [fontSize] + ); + + // Determine and Memoize Font Weight + const fontWeightValue = useMemo( + () => chartFontWeightMap[fontWeight], + [fontWeight, chartFontWeightMap] + ); + + // Memoize Chart Font Style + const chartFontStyle = useMemo( + () => ({ + family: fontFamily || "Arial", + size: fontSizeValue, + weight: fontWeightValue, + }), + [fontFamily, fontSizeValue, fontWeightValue] + ); + + const options = useMemo( + () => ({ + responsive: true, + maintainAspectRatio: false, + plugins: { + title: { + display: true, + text: title, + font: chartFontStyle, + }, + legend: { + display: false, + }, + }, + scales: { + x: { + ticks: { + display: false, // This hides the x-axis labels + }, + }, + }, + }), + [title, chartFontStyle] + ); + + const chartData = { + labels: ["January", "February", "March", "April", "May", "June", "July"], + datasets: [ + { + label: "My First Dataset", + data: [65, 59, 80, 81, 56, 55, 40], + backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple) + borderColor: "#ffffff", // Keeping border color white + borderWidth: 2, + fill: false, + }, + ], + }; + + return ; +}; + +export default LineGraphComponent; diff --git a/app/src/components/ui/charts/PieGraphComponent.tsx b/app/src/components/ui/charts/PieGraphComponent.tsx index b52ee30..0066ec3 100644 --- a/app/src/components/ui/charts/PieGraphComponent.tsx +++ b/app/src/components/ui/charts/PieGraphComponent.tsx @@ -1,91 +1,91 @@ -import { useMemo } from "react"; -import { Pie } from "react-chartjs-2"; - -interface ChartComponentProps { - type: any; - title: string; - fontFamily?: string; - fontSize?: string; - fontWeight?: "Light" | "Regular" | "Bold"; - data: any; -} - -const PieChartComponent = ({ - title, - fontFamily, - fontSize, - fontWeight = "Regular", -}: ChartComponentProps) => { - // Memoize Font Weight Mapping - const chartFontWeightMap = useMemo( - () => ({ - Light: "lighter" as const, - Regular: "normal" as const, - Bold: "bold" as const, - }), - [] - ); - - // Parse and Memoize Font Size - const fontSizeValue = useMemo( - () => (fontSize ? parseInt(fontSize) : 12), - [fontSize] - ); - - // Determine and Memoize Font Weight - const fontWeightValue = useMemo( - () => chartFontWeightMap[fontWeight], - [fontWeight, chartFontWeightMap] - ); - - // Memoize Chart Font Style - const chartFontStyle = useMemo( - () => ({ - family: fontFamily || "Arial", - size: fontSizeValue, - weight: fontWeightValue, - }), - [fontFamily, fontSizeValue, fontWeightValue] - ); - - // Access the CSS variable for the primary accent color - const accentColor = getComputedStyle(document.documentElement) - .getPropertyValue("--accent-color") - .trim(); - - console.log("accentColor: ", accentColor); - const options = useMemo( - () => ({ - responsive: true, - maintainAspectRatio: false, - plugins: { - title: { - display: true, - text: title, - font: chartFontStyle, - }, - legend: { - display: false, - }, - }, - }), - [title, chartFontStyle] - ); - - const chartData = { - labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], - datasets: [ - { - label: "Dataset", - data: [12, 19, 3, 5, 2, 3], - backgroundColor: ["#6f42c1"], - borderColor: "#ffffff", - borderWidth: 2, - }, - ], - }; - - return ; -}; - -export default PieChartComponent; +import { useMemo } from "react"; +import { Pie } from "react-chartjs-2"; + +interface ChartComponentProps { + type: any; + title: string; + fontFamily?: string; + fontSize?: string; + fontWeight?: "Light" | "Regular" | "Bold"; + data: any; +} + +const PieChartComponent = ({ + title, + fontFamily, + fontSize, + fontWeight = "Regular", +}: ChartComponentProps) => { + // Memoize Font Weight Mapping + const chartFontWeightMap = useMemo( + () => ({ + Light: "lighter" as const, + Regular: "normal" as const, + Bold: "bold" as const, + }), + [] + ); + + // Parse and Memoize Font Size + const fontSizeValue = useMemo( + () => (fontSize ? parseInt(fontSize) : 12), + [fontSize] + ); + + // Determine and Memoize Font Weight + const fontWeightValue = useMemo( + () => chartFontWeightMap[fontWeight], + [fontWeight, chartFontWeightMap] + ); + + // Memoize Chart Font Style + const chartFontStyle = useMemo( + () => ({ + family: fontFamily || "Arial", + size: fontSizeValue, + weight: fontWeightValue, + }), + [fontFamily, fontSizeValue, fontWeightValue] + ); + + // Access the CSS variable for the primary accent color + const accentColor = getComputedStyle(document.documentElement) + .getPropertyValue("--accent-color") + .trim(); + + console.log("accentColor: ", accentColor); + const options = useMemo( + () => ({ + responsive: true, + maintainAspectRatio: false, + plugins: { + title: { + display: true, + text: title, + font: chartFontStyle, + }, + legend: { + display: false, + }, + }, + }), + [title, chartFontStyle] + ); + + const chartData = { + labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], + datasets: [ + { + label: "Dataset", + data: [12, 19, 3, 5, 2, 3], + backgroundColor: ["#6f42c1"], + borderColor: "#ffffff", + borderWidth: 2, + }, + ], + }; + + return ; +}; + +export default PieChartComponent; diff --git a/app/src/components/ui/componets/DisplayZone.tsx b/app/src/components/ui/componets/DisplayZone.tsx index 3bf6b8f..85b9336 100644 --- a/app/src/components/ui/componets/DisplayZone.tsx +++ b/app/src/components/ui/componets/DisplayZone.tsx @@ -1,179 +1,179 @@ -import React, { useEffect, useRef } from "react"; -import { Widget } from "../../../store/useWidgetStore"; - -// Define the type for `Side` -type Side = "top" | "bottom" | "left" | "right"; - -interface DisplayZoneProps { - zonesData: { - [key: string]: { - activeSides: Side[]; - panelOrder: Side[]; - lockedPanels: Side[]; - widgets: Widget[]; - }; - }; - selectedZone: { - zoneName: string; - activeSides: Side[]; - panelOrder: Side[]; - lockedPanels: Side[]; - widgets: { - id: string; - type: string; - title: string; - panel: Side; - data: any; - }[]; - }; - setSelectedZone: React.Dispatch< - React.SetStateAction<{ - zoneName: string; - activeSides: Side[]; - panelOrder: Side[]; - lockedPanels: Side[]; - widgets: { - id: string; - type: string; - title: string; - panel: Side; - data: any; - }[]; - }> - >; -} - -const DisplayZone: React.FC = ({ - zonesData, - selectedZone, - setSelectedZone, -}) => { - // Ref for the container element - const containerRef = useRef(null); - - // Example state for selectedOption and options (adjust based on your actual use case) - const [selectedOption, setSelectedOption] = React.useState( - null - ); - console.log('setSelectedOption: ', setSelectedOption); - const [options, setOptions] = React.useState([]); - console.log('setOptions: ', setOptions); - - // Scroll to the selected option when it changes - useEffect(() => { - const container = containerRef.current; - - if (container && selectedOption) { - // Handle scrolling to the selected option - const index = options.findIndex((option) => { - const formattedOption = formatOptionName(option); - const selectedFormattedOption = - selectedOption?.split("_")[1] || selectedOption; - return formattedOption === selectedFormattedOption; - }); - - if (index !== -1) { - const optionElement = container.children[index] as HTMLElement; - if (optionElement) { - optionElement.scrollIntoView({ - behavior: "smooth", - block: "nearest", - inline: "center", - }); - } - } - } - }, [selectedOption, options]); - - useEffect(() => { - const container = containerRef.current; - - const handleWheel = (event: WheelEvent) => { - event.preventDefault(); - if (container) { - container.scrollBy({ - left: event.deltaY * 2, // Adjust the multiplier for faster scrolling - behavior: "smooth", - }); - } - }; - - let isDragging = false; - let startX: number; - let scrollLeft: number; - - const handleMouseDown = (event: MouseEvent) => { - isDragging = true; - startX = event.pageX - (container?.offsetLeft || 0); - scrollLeft = container?.scrollLeft || 0; - }; - - const handleMouseMove = (event: MouseEvent) => { - if (!isDragging || !container) return; - event.preventDefault(); - const x = event.pageX - (container.offsetLeft || 0); - const walk = (x - startX) * 2; // Adjust the multiplier for faster dragging - container.scrollLeft = scrollLeft - walk; - }; - - const handleMouseUp = () => { - isDragging = false; - }; - - const handleMouseLeave = () => { - isDragging = false; - }; - - if (container) { - container.addEventListener("wheel", handleWheel, { passive: false }); - container.addEventListener("mousedown", handleMouseDown); - container.addEventListener("mousemove", handleMouseMove); - container.addEventListener("mouseup", handleMouseUp); - container.addEventListener("mouseleave", handleMouseLeave); - } - - return () => { - if (container) { - container.removeEventListener("wheel", handleWheel); - container.removeEventListener("mousedown", handleMouseDown); - container.removeEventListener("mousemove", handleMouseMove); - container.removeEventListener("mouseup", handleMouseUp); - container.removeEventListener("mouseleave", handleMouseLeave); - } - }; - }, []); - - // Helper function to format option names (customize as needed) - const formatOptionName = (option: string): string => { - // Replace underscores with spaces and capitalize the first letter - return option.replace(/_/g, " ").replace(/^\w/, (c) => c.toUpperCase()); - }; - - return ( -
- {Object.keys(zonesData).map((zoneName, index) => ( -
{ - setSelectedZone({ - zoneName, - ...zonesData[zoneName], - }); - }} - > - {zoneName} -
- ))} -
- ); -}; - +import React, { useEffect, useRef } from "react"; +import { Widget } from "../../../store/useWidgetStore"; + +// Define the type for `Side` +type Side = "top" | "bottom" | "left" | "right"; + +interface DisplayZoneProps { + zonesData: { + [key: string]: { + activeSides: Side[]; + panelOrder: Side[]; + lockedPanels: Side[]; + widgets: Widget[]; + }; + }; + selectedZone: { + zoneName: string; + activeSides: Side[]; + panelOrder: Side[]; + lockedPanels: Side[]; + widgets: { + id: string; + type: string; + title: string; + panel: Side; + data: any; + }[]; + }; + setSelectedZone: React.Dispatch< + React.SetStateAction<{ + zoneName: string; + activeSides: Side[]; + panelOrder: Side[]; + lockedPanels: Side[]; + widgets: { + id: string; + type: string; + title: string; + panel: Side; + data: any; + }[]; + }> + >; +} + +const DisplayZone: React.FC = ({ + zonesData, + selectedZone, + setSelectedZone, +}) => { + // Ref for the container element + const containerRef = useRef(null); + + // Example state for selectedOption and options (adjust based on your actual use case) + const [selectedOption, setSelectedOption] = React.useState( + null + ); + // console.log('setSelectedOption: ', setSelectedOption); + const [options, setOptions] = React.useState([]); + // console.log('setOptions: ', setOptions); + + // Scroll to the selected option when it changes + useEffect(() => { + const container = containerRef.current; + + if (container && selectedOption) { + // Handle scrolling to the selected option + const index = options.findIndex((option) => { + const formattedOption = formatOptionName(option); + const selectedFormattedOption = + selectedOption?.split("_")[1] || selectedOption; + return formattedOption === selectedFormattedOption; + }); + + if (index !== -1) { + const optionElement = container.children[index] as HTMLElement; + if (optionElement) { + optionElement.scrollIntoView({ + behavior: "smooth", + block: "nearest", + inline: "center", + }); + } + } + } + }, [selectedOption, options]); + + useEffect(() => { + const container = containerRef.current; + + const handleWheel = (event: WheelEvent) => { + event.preventDefault(); + if (container) { + container.scrollBy({ + left: event.deltaY * 2, // Adjust the multiplier for faster scrolling + behavior: "smooth", + }); + } + }; + + let isDragging = false; + let startX: number; + let scrollLeft: number; + + const handleMouseDown = (event: MouseEvent) => { + isDragging = true; + startX = event.pageX - (container?.offsetLeft || 0); + scrollLeft = container?.scrollLeft || 0; + }; + + const handleMouseMove = (event: MouseEvent) => { + if (!isDragging || !container) return; + event.preventDefault(); + const x = event.pageX - (container.offsetLeft || 0); + const walk = (x - startX) * 2; // Adjust the multiplier for faster dragging + container.scrollLeft = scrollLeft - walk; + }; + + const handleMouseUp = () => { + isDragging = false; + }; + + const handleMouseLeave = () => { + isDragging = false; + }; + + if (container) { + container.addEventListener("wheel", handleWheel, { passive: false }); + container.addEventListener("mousedown", handleMouseDown); + container.addEventListener("mousemove", handleMouseMove); + container.addEventListener("mouseup", handleMouseUp); + container.addEventListener("mouseleave", handleMouseLeave); + } + + return () => { + if (container) { + container.removeEventListener("wheel", handleWheel); + container.removeEventListener("mousedown", handleMouseDown); + container.removeEventListener("mousemove", handleMouseMove); + container.removeEventListener("mouseup", handleMouseUp); + container.removeEventListener("mouseleave", handleMouseLeave); + } + }; + }, []); + + // Helper function to format option names (customize as needed) + const formatOptionName = (option: string): string => { + // Replace underscores with spaces and capitalize the first letter + return option.replace(/_/g, " ").replace(/^\w/, (c) => c.toUpperCase()); + }; + + return ( +
+ {Object.keys(zonesData).map((zoneName, index) => ( +
{ + setSelectedZone({ + zoneName, + ...zonesData[zoneName], + }); + }} + > + {zoneName} +
+ ))} +
+ ); +}; + export default DisplayZone; \ No newline at end of file diff --git a/app/src/components/ui/inputs/InputWithDropDown.tsx b/app/src/components/ui/inputs/InputWithDropDown.tsx index 99453d7..fa19af3 100644 --- a/app/src/components/ui/inputs/InputWithDropDown.tsx +++ b/app/src/components/ui/inputs/InputWithDropDown.tsx @@ -1,76 +1,76 @@ -import React, { useState } from "react"; -import RenameInput from "./RenameInput"; - -type InputWithDropDownProps = { - label: string; - value: string; - options?: string[]; // Array of dropdown options - activeOption?: string; // The currently active dropdown option - onClick?: () => void; - onChange: (newValue: string) => void; - editableLabel?: boolean; -}; - -const InputWithDropDown: React.FC = ({ - label, - value, - options, - activeOption, - onClick, - onChange, - editableLabel = false, -}) => { - const separatedWords = label - .split(/(?=[A-Z])/) - .map((word) => word.trim()) - .toString(); - - const [openDropdown, setOpenDropdown] = useState(false); - - return ( -
- {editableLabel ? ( - - ) : ( - - )} -
- { - onChange(e.target.value); - }} - /> - - {activeOption && ( -
{ - setOpenDropdown(true); - }} - > -
{activeOption}
- {options && openDropdown && ( -
- {options.map((option, index) => ( -
- {option} -
- ))} -
- )} -
- )} -
-
- ); -}; - -export default InputWithDropDown; +import React, { useState } from "react"; +import RenameInput from "./RenameInput"; + +type InputWithDropDownProps = { + label: string; + value: string; + options?: string[]; // Array of dropdown options + activeOption?: string; // The currently active dropdown option + onClick?: () => void; + onChange: (newValue: string) => void; + editableLabel?: boolean; +}; + +const InputWithDropDown: React.FC = ({ + label, + value, + options, + activeOption, + onClick, + onChange, + editableLabel = false, +}) => { + const separatedWords = label + .split(/(?=[A-Z])/) + .map((word) => word.trim()) + .toString(); + + const [openDropdown, setOpenDropdown] = useState(false); + + return ( +
+ {editableLabel ? ( + + ) : ( + + )} +
+ { + onChange(e.target.value); + }} + /> + + {activeOption && ( +
{ + setOpenDropdown(true); + }} + > +
{activeOption}
+ {options && openDropdown && ( +
+ {options.map((option, index) => ( +
+ {option} +
+ ))} +
+ )} +
+ )} +
+
+ ); +}; + +export default InputWithDropDown; diff --git a/app/src/components/ui/inputs/LabledDropdown.tsx b/app/src/components/ui/inputs/LabledDropdown.tsx index 197d5f1..29dbac5 100644 --- a/app/src/components/ui/inputs/LabledDropdown.tsx +++ b/app/src/components/ui/inputs/LabledDropdown.tsx @@ -1,29 +1,29 @@ -import React, { useState } from "react"; -import RegularDropDown from "./RegularDropDown"; - -type LabledDropdownProps = { - defaultOption: string; // Initial active option - options: string[]; // Array of dropdown options -}; - -const LabledDropdown: React.FC = ({ defaultOption, options }) => { - const [activeOption, setActiveOption] = useState(defaultOption); // State for active option - - const handleSelect = (option: string) => { - setActiveOption(option); // Update the active option state - }; - - return ( -
-
Type
- -
- ); -}; - -export default LabledDropdown; +import React, { useState } from "react"; +import RegularDropDown from "./RegularDropDown"; + +type LabledDropdownProps = { + defaultOption: string; // Initial active option + options: string[]; // Array of dropdown options +}; + +const LabledDropdown: React.FC = ({ defaultOption, options }) => { + const [activeOption, setActiveOption] = useState(defaultOption); // State for active option + + const handleSelect = (option: string) => { + setActiveOption(option); // Update the active option state + }; + + return ( +
+
Type
+ +
+ ); +}; + +export default LabledDropdown; diff --git a/app/src/components/ui/inputs/MultiLevelDropDown.tsx b/app/src/components/ui/inputs/MultiLevelDropDown.tsx index 8ea8d89..3c1780b 100644 --- a/app/src/components/ui/inputs/MultiLevelDropDown.tsx +++ b/app/src/components/ui/inputs/MultiLevelDropDown.tsx @@ -1,141 +1,141 @@ -import React, { useState, useRef, useEffect } from "react"; - -// Dropdown Item Component -const DropdownItem = ({ - label, - href, - onClick, -}: { - label: string; - href?: string; - onClick?: () => void; -}) => ( - { - e.preventDefault(); - onClick?.(); - }} - > - {label} - -); - -// Nested Dropdown Component -const NestedDropdown = ({ - label, - children, - onSelect, -}: { - label: string; - children: React.ReactNode; - onSelect: (selectedLabel: string) => void; -}) => { - const [open, setOpen] = useState(false); - - return ( -
- {/* Dropdown Trigger */} -
setOpen(!open)} // Toggle submenu on click - > - {label} {open ? "▼" : "▶"} -
- - {/* Submenu */} - {open && ( -
- {React.Children.map(children, (child) => { - if (React.isValidElement(child)) { - // Clone the element and pass the `onSelect` prop only if it's expected - return React.cloneElement(child as React.ReactElement, { onSelect }); - } - return child; // Return non-element children as-is - })} -
- )} -
- ); -}; - -// Recursive Function to Render Nested Data -const renderNestedData = ( - data: Record, - onSelect: (selectedLabel: string) => void -) => { - return Object.entries(data).map(([key, value]) => { - if (typeof value === "object" && !Array.isArray(value)) { - // If the value is an object, render it as a nested dropdown - return ( - - {renderNestedData(value, onSelect)} - - ); - } else if (Array.isArray(value)) { - // If the value is an array, render each item as a dropdown item - return value.map((item, index) => ( - onSelect(item)} /> - )); - } else { - // If the value is a simple string, render it as a dropdown item - return ( - onSelect(value)} /> - ); - } - }); -}; - -// Main Multi-Level Dropdown Component -const MultiLevelDropdown = ({ data }: { data: Record }) => { - const [open, setOpen] = useState(false); - const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger"); - const dropdownRef = useRef(null); - - // Handle outer click to close the dropdown - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if ( - dropdownRef.current && - !dropdownRef.current.contains(event.target as Node) - ) { - setOpen(false); - } - }; - - document.addEventListener("mousedown", handleClickOutside); - return () => { - document.removeEventListener("mousedown", handleClickOutside); - }; - }, []); - - // Handle selection of an item - const handleSelect = (selectedLabel: string) => { - setSelectedLabel(selectedLabel); // Update the dropdown trigger text - setOpen(false); // Close the dropdown - }; - - return ( -
- {/* Dropdown Trigger Button */} - - - {/* Dropdown Menu */} - {open && ( -
-
- {renderNestedData(data, handleSelect)} -
-
- )} -
- ); -}; - +import React, { useState, useRef, useEffect } from "react"; + +// Dropdown Item Component +const DropdownItem = ({ + label, + href, + onClick, +}: { + label: string; + href?: string; + onClick?: () => void; +}) => ( + { + e.preventDefault(); + onClick?.(); + }} + > + {label} + +); + +// Nested Dropdown Component +const NestedDropdown = ({ + label, + children, + onSelect, +}: { + label: string; + children: React.ReactNode; + onSelect: (selectedLabel: string) => void; +}) => { + const [open, setOpen] = useState(false); + + return ( +
+ {/* Dropdown Trigger */} +
setOpen(!open)} // Toggle submenu on click + > + {label} {open ? "▼" : "▶"} +
+ + {/* Submenu */} + {open && ( +
+ {React.Children.map(children, (child) => { + if (React.isValidElement(child)) { + // Clone the element and pass the `onSelect` prop only if it's expected + return React.cloneElement(child as React.ReactElement, { onSelect }); + } + return child; // Return non-element children as-is + })} +
+ )} +
+ ); +}; + +// Recursive Function to Render Nested Data +const renderNestedData = ( + data: Record, + onSelect: (selectedLabel: string) => void +) => { + return Object.entries(data).map(([key, value]) => { + if (typeof value === "object" && !Array.isArray(value)) { + // If the value is an object, render it as a nested dropdown + return ( + + {renderNestedData(value, onSelect)} + + ); + } else if (Array.isArray(value)) { + // If the value is an array, render each item as a dropdown item + return value.map((item, index) => ( + onSelect(item)} /> + )); + } else { + // If the value is a simple string, render it as a dropdown item + return ( + onSelect(value)} /> + ); + } + }); +}; + +// Main Multi-Level Dropdown Component +const MultiLevelDropdown = ({ data }: { data: Record }) => { + const [open, setOpen] = useState(false); + const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger"); + const dropdownRef = useRef(null); + + // Handle outer click to close the dropdown + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if ( + dropdownRef.current && + !dropdownRef.current.contains(event.target as Node) + ) { + setOpen(false); + } + }; + + document.addEventListener("mousedown", handleClickOutside); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, []); + + // Handle selection of an item + const handleSelect = (selectedLabel: string) => { + setSelectedLabel(selectedLabel); // Update the dropdown trigger text + setOpen(false); // Close the dropdown + }; + + return ( +
+ {/* Dropdown Trigger Button */} + + + {/* Dropdown Menu */} + {open && ( +
+
+ {renderNestedData(data, handleSelect)} +
+
+ )} +
+ ); +}; + export default MultiLevelDropdown; \ No newline at end of file diff --git a/app/src/components/ui/inputs/RegularDropDown.tsx b/app/src/components/ui/inputs/RegularDropDown.tsx index f08cc46..f1be25c 100644 --- a/app/src/components/ui/inputs/RegularDropDown.tsx +++ b/app/src/components/ui/inputs/RegularDropDown.tsx @@ -1,127 +1,127 @@ -import React, { useState, useEffect, useRef } from "react"; - -interface DropdownProps { - header: string; - options: string[]; - onSelect: (option: string) => void; - search?: boolean; - onClick?: () => void; - onChange?: () => void; -} - -const RegularDropDown: React.FC = ({ - header, - options, - onSelect, - search = true, - onClick, - onChange, -}) => { - const [isOpen, setIsOpen] = useState(false); - const [selectedOption, setSelectedOption] = useState(null); - const [searchTerm, setSearchTerm] = useState(""); // State to store search term - const [filteredOptions, setFilteredOptions] = useState(options); // State for filtered options - const dropdownRef = useRef(null); // Ref for the dropdown container - - // Reset selectedOption when the dropdown closes - useEffect(() => { - if (!isOpen) { - setSelectedOption(null); - setSearchTerm(""); // Clear the search term when the dropdown closes - setFilteredOptions(options); // Reset filtered options when the dropdown closes - } - }, [isOpen, options]); - - // Reset selectedOption when the header prop changes - useEffect(() => { - setSelectedOption(null); - setSearchTerm(""); // Reset search term if header changes - setFilteredOptions(options); // Reset options if header changes - }, [header, options]); - - // Close dropdown if clicked outside - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if ( - dropdownRef.current && - !dropdownRef.current.contains(event.target as Node) - ) { - setIsOpen(false); - } - }; - - document.addEventListener("click", handleClickOutside); - - return () => { - document.removeEventListener("click", handleClickOutside); - }; - }, []); - - // Toggle the dropdown - const toggleDropdown = () => { - setIsOpen((prev) => !prev); - }; - - // Handle option selection - const handleOptionClick = (option: string) => { - setSelectedOption(option); - onSelect(option); - setIsOpen(false); - }; - - // Handle search input change - const handleSearchChange = (event: React.ChangeEvent) => { - const term = event.target.value; - setSearchTerm(term); - - // Filter options based on the search term - const filtered = options.filter((option) => - option.toLowerCase().includes(term.toLowerCase()) - ); - setFilteredOptions(filtered); - }; - - return ( -
- {/* Dropdown Header */} -
-
{selectedOption || header}
-
-
- - {/* Dropdown Options */} - {isOpen && ( -
- {/* Search Bar */} - {search && ( -
- -
- )} - - {/* Filtered Options */} - {filteredOptions.length > 0 ? ( - filteredOptions.map((option, index) => ( -
handleOptionClick(option)} - > - {option} -
- )) - ) : ( -
No options found
- )} -
- )} -
- ); -}; - -export default RegularDropDown; +import React, { useState, useEffect, useRef } from "react"; + +interface DropdownProps { + header: string; + options: string[]; + onSelect: (option: string) => void; + search?: boolean; + onClick?: () => void; + onChange?: () => void; +} + +const RegularDropDown: React.FC = ({ + header, + options, + onSelect, + search = true, + onClick, + onChange, +}) => { + const [isOpen, setIsOpen] = useState(false); + const [selectedOption, setSelectedOption] = useState(null); + const [searchTerm, setSearchTerm] = useState(""); // State to store search term + const [filteredOptions, setFilteredOptions] = useState(options); // State for filtered options + const dropdownRef = useRef(null); // Ref for the dropdown container + + // Reset selectedOption when the dropdown closes + useEffect(() => { + if (!isOpen) { + setSelectedOption(null); + setSearchTerm(""); // Clear the search term when the dropdown closes + setFilteredOptions(options); // Reset filtered options when the dropdown closes + } + }, [isOpen, options]); + + // Reset selectedOption when the header prop changes + useEffect(() => { + setSelectedOption(null); + setSearchTerm(""); // Reset search term if header changes + setFilteredOptions(options); // Reset options if header changes + }, [header, options]); + + // Close dropdown if clicked outside + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if ( + dropdownRef.current && + !dropdownRef.current.contains(event.target as Node) + ) { + setIsOpen(false); + } + }; + + document.addEventListener("click", handleClickOutside); + + return () => { + document.removeEventListener("click", handleClickOutside); + }; + }, []); + + // Toggle the dropdown + const toggleDropdown = () => { + setIsOpen((prev) => !prev); + }; + + // Handle option selection + const handleOptionClick = (option: string) => { + setSelectedOption(option); + onSelect(option); + setIsOpen(false); + }; + + // Handle search input change + const handleSearchChange = (event: React.ChangeEvent) => { + const term = event.target.value; + setSearchTerm(term); + + // Filter options based on the search term + const filtered = options.filter((option) => + option.toLowerCase().includes(term.toLowerCase()) + ); + setFilteredOptions(filtered); + }; + + return ( +
+ {/* Dropdown Header */} +
+
{selectedOption || header}
+
+
+ + {/* Dropdown Options */} + {isOpen && ( +
+ {/* Search Bar */} + {search && ( +
+ +
+ )} + + {/* Filtered Options */} + {filteredOptions.length > 0 ? ( + filteredOptions.map((option, index) => ( +
handleOptionClick(option)} + > + {option} +
+ )) + ) : ( +
No options found
+ )} +
+ )} +
+ ); +}; + +export default RegularDropDown; diff --git a/app/src/functions/handleResizePannel.ts b/app/src/functions/handleResizePannel.ts index 235e97d..e989e05 100644 --- a/app/src/functions/handleResizePannel.ts +++ b/app/src/functions/handleResizePannel.ts @@ -1,24 +1,24 @@ -export const handleResize = ( - e: React.MouseEvent, - containerRef: React.RefObject -) => { - if (!containerRef.current) return; // Ensure containerRef is not null - const startY = e.clientY; - const startHeight = containerRef.current.offsetHeight; - - const onMouseMove = (moveEvent: MouseEvent) => { - const newHeight = Math.max( - 120, - Math.min(400, startHeight + moveEvent.clientY - startY) - ); - containerRef.current!.style.height = `${newHeight}px`; - }; - - const onMouseUp = () => { - document.removeEventListener("mousemove", onMouseMove); - document.removeEventListener("mouseup", onMouseUp); - }; - - document.addEventListener("mousemove", onMouseMove); - document.addEventListener("mouseup", onMouseUp); -}; +export const handleResize = ( + e: React.MouseEvent, + containerRef: React.RefObject +) => { + if (!containerRef.current) return; // Ensure containerRef is not null + const startY = e.clientY; + const startHeight = containerRef.current.offsetHeight; + + const onMouseMove = (moveEvent: MouseEvent) => { + const newHeight = Math.max( + 120, + Math.min(400, startHeight + moveEvent.clientY - startY) + ); + containerRef.current!.style.height = `${newHeight}px`; + }; + + const onMouseUp = () => { + document.removeEventListener("mousemove", onMouseMove); + document.removeEventListener("mouseup", onMouseUp); + }; + + document.addEventListener("mousemove", onMouseMove); + document.addEventListener("mouseup", onMouseUp); +}; diff --git a/app/src/index.css b/app/src/index.css index ec2585e..bd5bd6d 100644 --- a/app/src/index.css +++ b/app/src/index.css @@ -1,13 +1,13 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/app/src/index.tsx b/app/src/index.tsx index 8bcb621..f241ca6 100644 --- a/app/src/index.tsx +++ b/app/src/index.tsx @@ -1,19 +1,19 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import App from './app'; -import reportWebVitals from './reportWebVitals'; - -const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement -); -root.render( - - - -); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import App from './app'; +import reportWebVitals from './reportWebVitals'; + +const root = ReactDOM.createRoot( + document.getElementById('root') as HTMLElement +); +root.render( + + + +); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/app/src/modules/builder/csg/csg.tsx b/app/src/modules/builder/csg/csg.tsx index 0926710..f84fad0 100644 --- a/app/src/modules/builder/csg/csg.tsx +++ b/app/src/modules/builder/csg/csg.tsx @@ -1,54 +1,54 @@ -import * as THREE from "three"; -import { Geometry, Base, Subtraction } from "@react-three/csg"; -import { useDeleteModels } from "../../../store/store"; -import { useRef } from "react"; - -export interface CsgProps { - position: THREE.Vector3 | [number, number, number]; - scale: THREE.Vector3 | [number, number, number]; - model: THREE.Object3D; - hoveredDeletableWallItem: { current: THREE.Mesh | null }; -} - -export const Csg: React.FC = (props) => { - const { deleteModels } = useDeleteModels(); - const modelRef = useRef(); - const originalMaterials = useRef>(new Map()); - - const handleHover = (hovered: boolean, object: THREE.Mesh | null) => { - if (modelRef.current && deleteModels) { - modelRef.current.traverse((child) => { - if (child instanceof THREE.Mesh) { - if (!originalMaterials.current.has(child)) { - originalMaterials.current.set(child, child.material); - } - child.material = child.material.clone(); - child.material.color.set(hovered && deleteModels ? 0xff0000 : (originalMaterials.current.get(child) as any).color); - } - }); - } - props.hoveredDeletableWallItem.current = hovered ? object : null; - }; - - return ( - - - - - - - { - e.stopPropagation(); - handleHover(true, e.object.parent); - }} - onPointerOut={(e: any) => { - e.stopPropagation(); - handleHover(false, null); - }} - /> - - ); -}; +import * as THREE from "three"; +import { Geometry, Base, Subtraction } from "@react-three/csg"; +import { useDeleteModels } from "../../../store/store"; +import { useRef } from "react"; + +export interface CsgProps { + position: THREE.Vector3 | [number, number, number]; + scale: THREE.Vector3 | [number, number, number]; + model: THREE.Object3D; + hoveredDeletableWallItem: { current: THREE.Mesh | null }; +} + +export const Csg: React.FC = (props) => { + const { deleteModels } = useDeleteModels(); + const modelRef = useRef(); + const originalMaterials = useRef>(new Map()); + + const handleHover = (hovered: boolean, object: THREE.Mesh | null) => { + if (modelRef.current && deleteModels) { + modelRef.current.traverse((child) => { + if (child instanceof THREE.Mesh) { + if (!originalMaterials.current.has(child)) { + originalMaterials.current.set(child, child.material); + } + child.material = child.material.clone(); + child.material.color.set(hovered && deleteModels ? 0xff0000 : (originalMaterials.current.get(child) as any).color); + } + }); + } + props.hoveredDeletableWallItem.current = hovered ? object : null; + }; + + return ( + + + + + + + { + e.stopPropagation(); + handleHover(true, e.object.parent); + }} + onPointerOut={(e: any) => { + e.stopPropagation(); + handleHover(false, null); + }} + /> + + ); +}; diff --git a/app/src/modules/builder/eventDeclaration/dragControlDeclaration.ts b/app/src/modules/builder/eventDeclaration/dragControlDeclaration.ts index 3e5bc5c..d0921dd 100644 --- a/app/src/modules/builder/eventDeclaration/dragControlDeclaration.ts +++ b/app/src/modules/builder/eventDeclaration/dragControlDeclaration.ts @@ -1,80 +1,80 @@ -import * as THREE from 'three'; -import { DragControls } from 'three/examples/jsm/controls/DragControls'; -import * as CONSTANTS from '../../../types/world/worldConstants'; -import DragPoint from '../geomentries/points/dragPoint'; - -import * as Types from "../../../types/world/worldTypes"; -// import { updatePoint } from '../../../services/factoryBuilder/lines/updatePointApi'; -import { Socket } from 'socket.io-client'; - -export default async function addDragControl( - dragPointControls: Types.RefDragControl, - currentLayerPoint: Types.RefMeshArray, - state: Types.ThreeState, - floorPlanGroupPoint: Types.RefGroup, - floorPlanGroupLine: Types.RefGroup, - lines: Types.RefLines, - onlyFloorlines: Types.RefOnlyFloorLines, - socket: Socket -) { - - ////////// Dragging Point and also change the size to indicate during hover ////////// - - dragPointControls.current = new DragControls(currentLayerPoint.current, state.camera, state.gl.domElement); - dragPointControls.current.enabled = false; - - dragPointControls.current.addEventListener('drag', function (event) { - const object = event.object; - if (object.visible) { - (state.controls as any).enabled = false; - DragPoint(event as any, floorPlanGroupPoint, floorPlanGroupLine, state.scene, lines, onlyFloorlines) - } else { - (state.controls as any).enabled = true; - } - }); - - dragPointControls.current.addEventListener('dragstart', function (event) { - }); - - dragPointControls.current.addEventListener('dragend', async function (event) { - if (!dragPointControls.current) return; - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // await updatePoint( - // organization, - // { "x": event.object.position.x, "y": 0.01, "z": event.object.position.z }, - // event.object.uuid, - // ) - - //SOCKET - - const data = { - organization: organization, - position: { "x": event.object.position.x, "y": 0.01, "z": event.object.position.z }, - uuid: event.object.uuid, - socketId: socket.id - } - - socket.emit('v1:Line:update', data); - - if (state.controls) { - (state.controls as any).enabled = true; - } - }); - - dragPointControls.current.addEventListener('hoveron', function (event: any) { - if ((event.object as Types.Mesh).name === "point") { - event.object.material.uniforms.uInnerColor.value.set(event.object.userData.color) - } - }); - - dragPointControls.current.addEventListener('hoveroff', function (event: any) { - if ((event.object as Types.Mesh).name === "point") { - event.object.material.uniforms.uInnerColor.value.set(new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor)) - } - }); - +import * as THREE from 'three'; +import { DragControls } from 'three/examples/jsm/controls/DragControls'; +import * as CONSTANTS from '../../../types/world/worldConstants'; +import DragPoint from '../geomentries/points/dragPoint'; + +import * as Types from "../../../types/world/worldTypes"; +// import { updatePoint } from '../../../services/factoryBuilder/lines/updatePointApi'; +import { Socket } from 'socket.io-client'; + +export default async function addDragControl( + dragPointControls: Types.RefDragControl, + currentLayerPoint: Types.RefMeshArray, + state: Types.ThreeState, + floorPlanGroupPoint: Types.RefGroup, + floorPlanGroupLine: Types.RefGroup, + lines: Types.RefLines, + onlyFloorlines: Types.RefOnlyFloorLines, + socket: Socket +) { + + ////////// Dragging Point and also change the size to indicate during hover ////////// + + dragPointControls.current = new DragControls(currentLayerPoint.current, state.camera, state.gl.domElement); + dragPointControls.current.enabled = false; + + dragPointControls.current.addEventListener('drag', function (event) { + const object = event.object; + if (object.visible) { + (state.controls as any).enabled = false; + DragPoint(event as any, floorPlanGroupPoint, floorPlanGroupLine, state.scene, lines, onlyFloorlines) + } else { + (state.controls as any).enabled = true; + } + }); + + dragPointControls.current.addEventListener('dragstart', function (event) { + }); + + dragPointControls.current.addEventListener('dragend', async function (event) { + if (!dragPointControls.current) return; + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // await updatePoint( + // organization, + // { "x": event.object.position.x, "y": 0.01, "z": event.object.position.z }, + // event.object.uuid, + // ) + + //SOCKET + + const data = { + organization: organization, + position: { "x": event.object.position.x, "y": 0.01, "z": event.object.position.z }, + uuid: event.object.uuid, + socketId: socket.id + } + + socket.emit('v1:Line:update', data); + + if (state.controls) { + (state.controls as any).enabled = true; + } + }); + + dragPointControls.current.addEventListener('hoveron', function (event: any) { + if ((event.object as Types.Mesh).name === "point") { + event.object.material.uniforms.uInnerColor.value.set(event.object.userData.color) + } + }); + + dragPointControls.current.addEventListener('hoveroff', function (event: any) { + if ((event.object as Types.Mesh).name === "point") { + event.object.material.uniforms.uInnerColor.value.set(new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor)) + } + }); + } \ No newline at end of file diff --git a/app/src/modules/builder/eventFunctions/handleContextMenu.ts b/app/src/modules/builder/eventFunctions/handleContextMenu.ts index fad1e64..454f847 100644 --- a/app/src/modules/builder/eventFunctions/handleContextMenu.ts +++ b/app/src/modules/builder/eventFunctions/handleContextMenu.ts @@ -1,8 +1,8 @@ -import * as Types from "../../../types/world/worldTypes"; - -export default function handleContextMenu( - menuVisible: Types.Boolean, - setMenuVisible: Types.BooleanState -): void { - // setMenuVisible(true) +import * as Types from "../../../types/world/worldTypes"; + +export default function handleContextMenu( + menuVisible: Types.Boolean, + setMenuVisible: Types.BooleanState +): void { + // setMenuVisible(true) } \ No newline at end of file diff --git a/app/src/modules/builder/eventFunctions/handleMeshDown.ts b/app/src/modules/builder/eventFunctions/handleMeshDown.ts index 43806b8..1f00038 100644 --- a/app/src/modules/builder/eventFunctions/handleMeshDown.ts +++ b/app/src/modules/builder/eventFunctions/handleMeshDown.ts @@ -1,64 +1,64 @@ -import * as THREE from 'three'; - -import * as Types from "../../../types/world/worldTypes"; - -function handleMeshDown( - event: Types.MeshEvent, - currentWallItem: Types.RefMesh, - setSelectedWallItem: Types.setSelectedWallItemSetState, - setSelectedItemsIndex: Types.setSelectedItemsIndexSetState, - wallItems: Types.wallItems, - toggleView: Types.Boolean -): void { - - ////////// To select which of the Wall item and CSG is selected to be dragged ////////// - - if (!toggleView) { - if (currentWallItem.current) { - currentWallItem.current.children.forEach((child) => { - if ((child as THREE.Mesh).isMesh && child.name !== "CSG_REF") { - const material = (child as THREE.Mesh).material; - if (Array.isArray(material)) { - material.forEach(mat => { - if (mat instanceof THREE.MeshStandardMaterial) { - mat.emissive = new THREE.Color("black"); - } - }); - } else if (material instanceof THREE.MeshStandardMaterial) { - material.emissive = new THREE.Color("black"); - } - } - }); - currentWallItem.current = null; - setSelectedWallItem(null); - setSelectedItemsIndex(null); - } - - if (event.intersections.length > 0) { - const clickedIndex = wallItems.findIndex((item) => item.model === event.intersections[0]?.object?.parent?.parent); - if (clickedIndex !== -1) { - setSelectedItemsIndex(clickedIndex); - const wallItemModel = wallItems[clickedIndex]?.model; - if (wallItemModel && wallItemModel.parent && wallItemModel.parent.parent) { - currentWallItem.current = (wallItemModel.parent.parent.children[0]?.children[1]?.children[0] as Types.Mesh) || null; - setSelectedWallItem(wallItemModel.parent); - // currentWallItem.current?.children.forEach((child) => { - // if ((child as THREE.Mesh).isMesh && child.name !== "CSG_REF") { - // const material = (child as THREE.Mesh).material; - // if (Array.isArray(material)) { - // material.forEach(mat => { - // if (mat instanceof THREE.MeshStandardMaterial) { - // mat.emissive = new THREE.Color("green"); - // } - // }); - // } else if (material instanceof THREE.MeshStandardMaterial) { - // material.emissive = new THREE.Color("green"); - // } - // } - // }); - } - } - } - } -} -export default handleMeshDown; +import * as THREE from 'three'; + +import * as Types from "../../../types/world/worldTypes"; + +function handleMeshDown( + event: Types.MeshEvent, + currentWallItem: Types.RefMesh, + setSelectedWallItem: Types.setSelectedWallItemSetState, + setSelectedItemsIndex: Types.setSelectedItemsIndexSetState, + wallItems: Types.wallItems, + toggleView: Types.Boolean +): void { + + ////////// To select which of the Wall item and CSG is selected to be dragged ////////// + + if (!toggleView) { + if (currentWallItem.current) { + currentWallItem.current.children.forEach((child) => { + if ((child as THREE.Mesh).isMesh && child.name !== "CSG_REF") { + const material = (child as THREE.Mesh).material; + if (Array.isArray(material)) { + material.forEach(mat => { + if (mat instanceof THREE.MeshStandardMaterial) { + mat.emissive = new THREE.Color("black"); + } + }); + } else if (material instanceof THREE.MeshStandardMaterial) { + material.emissive = new THREE.Color("black"); + } + } + }); + currentWallItem.current = null; + setSelectedWallItem(null); + setSelectedItemsIndex(null); + } + + if (event.intersections.length > 0) { + const clickedIndex = wallItems.findIndex((item) => item.model === event.intersections[0]?.object?.parent?.parent); + if (clickedIndex !== -1) { + setSelectedItemsIndex(clickedIndex); + const wallItemModel = wallItems[clickedIndex]?.model; + if (wallItemModel && wallItemModel.parent && wallItemModel.parent.parent) { + currentWallItem.current = (wallItemModel.parent.parent.children[0]?.children[1]?.children[0] as Types.Mesh) || null; + setSelectedWallItem(wallItemModel.parent); + // currentWallItem.current?.children.forEach((child) => { + // if ((child as THREE.Mesh).isMesh && child.name !== "CSG_REF") { + // const material = (child as THREE.Mesh).material; + // if (Array.isArray(material)) { + // material.forEach(mat => { + // if (mat instanceof THREE.MeshStandardMaterial) { + // mat.emissive = new THREE.Color("green"); + // } + // }); + // } else if (material instanceof THREE.MeshStandardMaterial) { + // material.emissive = new THREE.Color("green"); + // } + // } + // }); + } + } + } + } +} +export default handleMeshDown; diff --git a/app/src/modules/builder/eventFunctions/handleMeshMissed.ts b/app/src/modules/builder/eventFunctions/handleMeshMissed.ts index 9588a48..f374831 100644 --- a/app/src/modules/builder/eventFunctions/handleMeshMissed.ts +++ b/app/src/modules/builder/eventFunctions/handleMeshMissed.ts @@ -1,34 +1,34 @@ -import * as THREE from 'three'; -import * as Types from "../../../types/world/worldTypes"; - -function handleMeshMissed( - currentWallItem: Types.RefMesh, - setSelectedWallItem: Types.setSelectedWallItemSetState, - setSelectedItemsIndex: Types.setSelectedItemsIndexSetState -): void { - - ////////// If an item is selected and then clicked outside other than the selected object, this runs and removes the color of the selected object and sets setSelectedWallItem and setSelectedItemsIndex as null ////////// - - if (currentWallItem.current) { - currentWallItem.current.children.forEach((child) => { - if ((child as THREE.Mesh).isMesh && child.name !== "CSG_REF") { - const material = (child as THREE.Mesh).material; - - if (Array.isArray(material)) { - material.forEach(mat => { - if (mat instanceof THREE.MeshStandardMaterial) { - mat.emissive = new THREE.Color("black"); - } - }); - } else if (material instanceof THREE.MeshStandardMaterial) { - material.emissive = new THREE.Color("black"); - } - } - }); - currentWallItem.current = null; - setSelectedWallItem(null); - setSelectedItemsIndex(null); - } -} - -export default handleMeshMissed; +import * as THREE from 'three'; +import * as Types from "../../../types/world/worldTypes"; + +function handleMeshMissed( + currentWallItem: Types.RefMesh, + setSelectedWallItem: Types.setSelectedWallItemSetState, + setSelectedItemsIndex: Types.setSelectedItemsIndexSetState +): void { + + ////////// If an item is selected and then clicked outside other than the selected object, this runs and removes the color of the selected object and sets setSelectedWallItem and setSelectedItemsIndex as null ////////// + + if (currentWallItem.current) { + currentWallItem.current.children.forEach((child) => { + if ((child as THREE.Mesh).isMesh && child.name !== "CSG_REF") { + const material = (child as THREE.Mesh).material; + + if (Array.isArray(material)) { + material.forEach(mat => { + if (mat instanceof THREE.MeshStandardMaterial) { + mat.emissive = new THREE.Color("black"); + } + }); + } else if (material instanceof THREE.MeshStandardMaterial) { + material.emissive = new THREE.Color("black"); + } + } + }); + currentWallItem.current = null; + setSelectedWallItem(null); + setSelectedItemsIndex(null); + } +} + +export default handleMeshMissed; diff --git a/app/src/modules/builder/functions/deletableLineOrPoint.ts b/app/src/modules/builder/functions/deletableLineOrPoint.ts index 423c581..2690bf7 100644 --- a/app/src/modules/builder/functions/deletableLineOrPoint.ts +++ b/app/src/modules/builder/functions/deletableLineOrPoint.ts @@ -1,87 +1,87 @@ -import * as THREE from 'three'; -import * as CONSTANTS from '../../../types/world/worldConstants'; -import * as Types from "../../../types/world/worldTypes"; - -function DeletableLineorPoint( - state: Types.ThreeState, - plane: Types.RefMesh, - floorPlanGroupLine: Types.RefGroup, - floorPlanGroupPoint: Types.RefGroup, - hoveredDeletableLine: Types.RefMesh, - hoveredDeletablePoint: Types.RefMesh -): void { - - ////////// Altering the color of the hovered line or point during the deletion time ////////// - - if (!plane.current) return; - let intersects = state.raycaster.intersectObject(plane.current, true); - - let visibleIntersectLines; - if (floorPlanGroupLine.current) { visibleIntersectLines = state.raycaster?.intersectObjects(floorPlanGroupLine.current.children, true); } - const visibleIntersectLine = visibleIntersectLines?.find(intersect => intersect.object.visible) as THREE.Line | undefined || null; - - let visibleIntersectPoints; - if (floorPlanGroupPoint.current) { - visibleIntersectPoints = state.raycaster?.intersectObjects(floorPlanGroupPoint.current.children, true); - } - const visibleIntersectPoint = visibleIntersectPoints?.find(intersect => intersect.object.visible) as THREE.Mesh | undefined; - - function getLineColor(lineType: string | undefined): string { - switch (lineType) { - case CONSTANTS.lineConfig.wallName: return CONSTANTS.lineConfig.wallColor; - case CONSTANTS.lineConfig.floorName: return CONSTANTS.lineConfig.floorColor; - case CONSTANTS.lineConfig.aisleName: return CONSTANTS.lineConfig.aisleColor; - default: return CONSTANTS.lineConfig.defaultColor; - } - } - - if (intersects.length > 0) { - if (visibleIntersectPoint) { - if (hoveredDeletableLine.current) { - const lineType = hoveredDeletableLine.current.userData.linePoints[1]?.[3]; - const color = getLineColor(lineType); - (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color(color); - hoveredDeletableLine.current = null; - } - - hoveredDeletablePoint.current = (visibleIntersectPoint as any).object; - (hoveredDeletablePoint.current as any).material.uniforms.uInnerColor.value.set(new THREE.Color("red")); - (hoveredDeletablePoint.current as any).material.uniforms.uColor.value.set(new THREE.Color("red")); - // (hoveredDeletablePoint.current as THREE.Mesh).scale.set(1.5, 1.5, 1.5); - } else if (hoveredDeletablePoint.current) { - (hoveredDeletablePoint.current as any).material.uniforms.uInnerColor.value.set(CONSTANTS.pointConfig.defaultInnerColor); - (hoveredDeletablePoint.current as any).material.uniforms.uColor.value.set((hoveredDeletablePoint.current as any).userData.color); - // hoveredDeletablePoint.current.scale.set(1, 1, 1); - hoveredDeletablePoint.current = null; - } - - if (visibleIntersectLine && !visibleIntersectPoint) { - if (hoveredDeletableLine.current) { - const lineType = hoveredDeletableLine.current.userData.linePoints[1]?.[3]; - const color = getLineColor(lineType); - (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color(color); - hoveredDeletableLine.current = null; - } - - if (hoveredDeletablePoint.current) { - (hoveredDeletablePoint.current as any).material.uniforms.uInnerColor.value.set(CONSTANTS.pointConfig.defaultInnerColor); - (hoveredDeletablePoint.current as any).material.uniforms.uColor.value.set((hoveredDeletablePoint.current as any).userData.color); - // hoveredDeletablePoint.current.scale.set(1, 1, 1); - hoveredDeletablePoint.current = null; - } - - hoveredDeletableLine.current = (visibleIntersectLine as any).object; - if (hoveredDeletableLine.current) { - (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color("red"); - } - } else if (hoveredDeletableLine.current) { - const lineType = hoveredDeletableLine.current.userData.linePoints[1]?.[3]; - const color = getLineColor(lineType); - (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color(color); - hoveredDeletableLine.current = null; - } - } - -} - -export default DeletableLineorPoint; +import * as THREE from 'three'; +import * as CONSTANTS from '../../../types/world/worldConstants'; +import * as Types from "../../../types/world/worldTypes"; + +function DeletableLineorPoint( + state: Types.ThreeState, + plane: Types.RefMesh, + floorPlanGroupLine: Types.RefGroup, + floorPlanGroupPoint: Types.RefGroup, + hoveredDeletableLine: Types.RefMesh, + hoveredDeletablePoint: Types.RefMesh +): void { + + ////////// Altering the color of the hovered line or point during the deletion time ////////// + + if (!plane.current) return; + let intersects = state.raycaster.intersectObject(plane.current, true); + + let visibleIntersectLines; + if (floorPlanGroupLine.current) { visibleIntersectLines = state.raycaster?.intersectObjects(floorPlanGroupLine.current.children, true); } + const visibleIntersectLine = visibleIntersectLines?.find(intersect => intersect.object.visible) as THREE.Line | undefined || null; + + let visibleIntersectPoints; + if (floorPlanGroupPoint.current) { + visibleIntersectPoints = state.raycaster?.intersectObjects(floorPlanGroupPoint.current.children, true); + } + const visibleIntersectPoint = visibleIntersectPoints?.find(intersect => intersect.object.visible) as THREE.Mesh | undefined; + + function getLineColor(lineType: string | undefined): string { + switch (lineType) { + case CONSTANTS.lineConfig.wallName: return CONSTANTS.lineConfig.wallColor; + case CONSTANTS.lineConfig.floorName: return CONSTANTS.lineConfig.floorColor; + case CONSTANTS.lineConfig.aisleName: return CONSTANTS.lineConfig.aisleColor; + default: return CONSTANTS.lineConfig.defaultColor; + } + } + + if (intersects.length > 0) { + if (visibleIntersectPoint) { + if (hoveredDeletableLine.current) { + const lineType = hoveredDeletableLine.current.userData.linePoints[1]?.[3]; + const color = getLineColor(lineType); + (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color(color); + hoveredDeletableLine.current = null; + } + + hoveredDeletablePoint.current = (visibleIntersectPoint as any).object; + (hoveredDeletablePoint.current as any).material.uniforms.uInnerColor.value.set(new THREE.Color("red")); + (hoveredDeletablePoint.current as any).material.uniforms.uColor.value.set(new THREE.Color("red")); + // (hoveredDeletablePoint.current as THREE.Mesh).scale.set(1.5, 1.5, 1.5); + } else if (hoveredDeletablePoint.current) { + (hoveredDeletablePoint.current as any).material.uniforms.uInnerColor.value.set(CONSTANTS.pointConfig.defaultInnerColor); + (hoveredDeletablePoint.current as any).material.uniforms.uColor.value.set((hoveredDeletablePoint.current as any).userData.color); + // hoveredDeletablePoint.current.scale.set(1, 1, 1); + hoveredDeletablePoint.current = null; + } + + if (visibleIntersectLine && !visibleIntersectPoint) { + if (hoveredDeletableLine.current) { + const lineType = hoveredDeletableLine.current.userData.linePoints[1]?.[3]; + const color = getLineColor(lineType); + (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color(color); + hoveredDeletableLine.current = null; + } + + if (hoveredDeletablePoint.current) { + (hoveredDeletablePoint.current as any).material.uniforms.uInnerColor.value.set(CONSTANTS.pointConfig.defaultInnerColor); + (hoveredDeletablePoint.current as any).material.uniforms.uColor.value.set((hoveredDeletablePoint.current as any).userData.color); + // hoveredDeletablePoint.current.scale.set(1, 1, 1); + hoveredDeletablePoint.current = null; + } + + hoveredDeletableLine.current = (visibleIntersectLine as any).object; + if (hoveredDeletableLine.current) { + (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color("red"); + } + } else if (hoveredDeletableLine.current) { + const lineType = hoveredDeletableLine.current.userData.linePoints[1]?.[3]; + const color = getLineColor(lineType); + (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color(color); + hoveredDeletableLine.current = null; + } + } + +} + +export default DeletableLineorPoint; diff --git a/app/src/modules/builder/functions/draw.ts b/app/src/modules/builder/functions/draw.ts index 341c741..fc4dafa 100644 --- a/app/src/modules/builder/functions/draw.ts +++ b/app/src/modules/builder/functions/draw.ts @@ -1,97 +1,97 @@ -import * as Types from "../../../types/world/worldTypes"; -import * as CONSTANTS from '../../../types/world/worldConstants'; -import createAndMoveReferenceLine from "../geomentries/lines/createAndMoveReferenceLine"; - -async function Draw( - state: Types.ThreeState, - plane: Types.RefMesh, - cursorPosition: Types.Vector3, - floorPlanGroupPoint: Types.RefGroup, - floorPlanGroupLine: Types.RefGroup, - snappedPoint: Types.RefVector3, - isSnapped: Types.RefBoolean, - isSnappedUUID: Types.RefString, - line: Types.RefLine, - lines: Types.RefLines, - ispreSnapped: Types.RefBoolean, - floorPlanGroup: Types.RefGroup, - ReferenceLineMesh: Types.RefMesh, - LineCreated: Types.RefBoolean, - setRefTextUpdate: Types.NumberIncrementState, - Tube: Types.RefTubeGeometry, - anglesnappedPoint: Types.RefVector3, - isAngleSnapped: Types.RefBoolean, - toolMode: Types.String, -): Promise { - - ////////// Snapping the cursor during the drawing time and also changing the color of the intersected lines ////////// - - if (!plane.current) return; - const intersects = state.raycaster.intersectObject(plane.current, true); - - if (intersects.length > 0 && (toolMode === "Wall" || toolMode === "Aisle" || toolMode === "Floor")) { - const intersectionPoint = intersects[0].point; - cursorPosition.copy(intersectionPoint); - const snapThreshold = 1; - - if (line.current.length === 0) { - for (const point of floorPlanGroupPoint.current.children) { - const pointType = point.userData.type; - - const canSnap = - ((toolMode === "Wall") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName)) || - ((toolMode === "Floor") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName)) || - ((toolMode === "Aisle") && pointType === CONSTANTS.lineConfig.aisleName);; - - if (canSnap && cursorPosition.distanceTo(point.position) < snapThreshold + 0.5 && point.visible) { - cursorPosition.copy(point.position); - snappedPoint.current = point.position; - ispreSnapped.current = true; - isSnapped.current = false; - isSnappedUUID.current = point.uuid; - break; - } else { - ispreSnapped.current = false; - } - } - } else if (line.current.length > 0 && line.current[0]) { - for (const point of floorPlanGroupPoint.current.children) { - const pointType = point.userData.type; - - let canSnap = - ((toolMode === "Wall") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName)) || - ((toolMode === "Floor") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName)) || - ((toolMode === "Aisle") && pointType === CONSTANTS.lineConfig.aisleName); - - if (canSnap && cursorPosition.distanceTo(point.position) < snapThreshold && point.visible) { - cursorPosition.copy(point.position); - snappedPoint.current = point.position; - isSnapped.current = true; - ispreSnapped.current = false; - isSnappedUUID.current = point.uuid; - break; - } else { - isSnapped.current = false; - } - } - - createAndMoveReferenceLine( - line.current[0][0], - cursorPosition, - isSnapped, - ispreSnapped, - line, - setRefTextUpdate, - floorPlanGroup, - ReferenceLineMesh, - LineCreated, - Tube, - anglesnappedPoint, - isAngleSnapped - ); - } - } - -} - +import * as Types from "../../../types/world/worldTypes"; +import * as CONSTANTS from '../../../types/world/worldConstants'; +import createAndMoveReferenceLine from "../geomentries/lines/createAndMoveReferenceLine"; + +async function Draw( + state: Types.ThreeState, + plane: Types.RefMesh, + cursorPosition: Types.Vector3, + floorPlanGroupPoint: Types.RefGroup, + floorPlanGroupLine: Types.RefGroup, + snappedPoint: Types.RefVector3, + isSnapped: Types.RefBoolean, + isSnappedUUID: Types.RefString, + line: Types.RefLine, + lines: Types.RefLines, + ispreSnapped: Types.RefBoolean, + floorPlanGroup: Types.RefGroup, + ReferenceLineMesh: Types.RefMesh, + LineCreated: Types.RefBoolean, + setRefTextUpdate: Types.NumberIncrementState, + Tube: Types.RefTubeGeometry, + anglesnappedPoint: Types.RefVector3, + isAngleSnapped: Types.RefBoolean, + toolMode: Types.String, +): Promise { + + ////////// Snapping the cursor during the drawing time and also changing the color of the intersected lines ////////// + + if (!plane.current) return; + const intersects = state.raycaster.intersectObject(plane.current, true); + + if (intersects.length > 0 && (toolMode === "Wall" || toolMode === "Aisle" || toolMode === "Floor")) { + const intersectionPoint = intersects[0].point; + cursorPosition.copy(intersectionPoint); + const snapThreshold = 1; + + if (line.current.length === 0) { + for (const point of floorPlanGroupPoint.current.children) { + const pointType = point.userData.type; + + const canSnap = + ((toolMode === "Wall") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName)) || + ((toolMode === "Floor") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName)) || + ((toolMode === "Aisle") && pointType === CONSTANTS.lineConfig.aisleName);; + + if (canSnap && cursorPosition.distanceTo(point.position) < snapThreshold + 0.5 && point.visible) { + cursorPosition.copy(point.position); + snappedPoint.current = point.position; + ispreSnapped.current = true; + isSnapped.current = false; + isSnappedUUID.current = point.uuid; + break; + } else { + ispreSnapped.current = false; + } + } + } else if (line.current.length > 0 && line.current[0]) { + for (const point of floorPlanGroupPoint.current.children) { + const pointType = point.userData.type; + + let canSnap = + ((toolMode === "Wall") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName)) || + ((toolMode === "Floor") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName)) || + ((toolMode === "Aisle") && pointType === CONSTANTS.lineConfig.aisleName); + + if (canSnap && cursorPosition.distanceTo(point.position) < snapThreshold && point.visible) { + cursorPosition.copy(point.position); + snappedPoint.current = point.position; + isSnapped.current = true; + ispreSnapped.current = false; + isSnappedUUID.current = point.uuid; + break; + } else { + isSnapped.current = false; + } + } + + createAndMoveReferenceLine( + line.current[0][0], + cursorPosition, + isSnapped, + ispreSnapped, + line, + setRefTextUpdate, + floorPlanGroup, + ReferenceLineMesh, + LineCreated, + Tube, + anglesnappedPoint, + isAngleSnapped + ); + } + } + +} + export default Draw; \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/aisles/addAilseToScene.ts b/app/src/modules/builder/geomentries/aisles/addAilseToScene.ts index 9cd74ed..80002b9 100644 --- a/app/src/modules/builder/geomentries/aisles/addAilseToScene.ts +++ b/app/src/modules/builder/geomentries/aisles/addAilseToScene.ts @@ -1,56 +1,56 @@ -import * as THREE from 'three'; -import * as Types from '../../../../types/world/worldTypes'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; - -export default async function addAisleToScene( - aisle: Types.Line, - floorGroupAisle: Types.RefGroup, -): Promise { - if (aisle.length >= 2 && aisle[0] && aisle[1]) { - const start: Types.Vector3 = aisle[0][0]; - const end: Types.Vector3 = aisle[1][0]; - - const direction = new THREE.Vector3( - end.x - start.x, - end.y - start.y, - end.z - start.z - ).normalize(); - - const perp = new THREE.Vector3(-direction.z, 0, direction.x).normalize(); - const offsetDistance = CONSTANTS.aisleConfig.width; - - const leftStart = new THREE.Vector3().copy(start).addScaledVector(perp, offsetDistance); - const rightStart = new THREE.Vector3().copy(start).addScaledVector(perp, -offsetDistance); - const leftEnd = new THREE.Vector3().copy(end).addScaledVector(perp, offsetDistance); - const rightEnd = new THREE.Vector3().copy(end).addScaledVector(perp, -offsetDistance); - - const stripShape = new THREE.Shape(); - stripShape.moveTo(leftStart.x, leftStart.z); - stripShape.lineTo(leftEnd.x, leftEnd.z); - stripShape.lineTo(rightEnd.x, rightEnd.z); - stripShape.lineTo(rightStart.x, rightStart.z); - stripShape.lineTo(leftStart.x, leftStart.z); - - const extrudeSettings = { - depth: CONSTANTS.aisleConfig.height, - bevelEnabled: false, - }; - - const stripGeometry = new THREE.ExtrudeGeometry(stripShape, extrudeSettings); - const stripMaterial = new THREE.MeshStandardMaterial({ - color: CONSTANTS.aisleConfig.defaultColor, - polygonOffset: true, - polygonOffsetFactor: -1, - polygonOffsetUnits: -1, - }); - - const stripMesh = new THREE.Mesh(stripGeometry, stripMaterial); - stripMesh.receiveShadow = true; - stripMesh.castShadow = true; - - stripMesh.position.y = (aisle[0][2] - 1) * CONSTANTS.wallConfig.height + 0.01; - stripMesh.rotateX(Math.PI / 2); - - floorGroupAisle.current.add(stripMesh); - } -} +import * as THREE from 'three'; +import * as Types from '../../../../types/world/worldTypes'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; + +export default async function addAisleToScene( + aisle: Types.Line, + floorGroupAisle: Types.RefGroup, +): Promise { + if (aisle.length >= 2 && aisle[0] && aisle[1]) { + const start: Types.Vector3 = aisle[0][0]; + const end: Types.Vector3 = aisle[1][0]; + + const direction = new THREE.Vector3( + end.x - start.x, + end.y - start.y, + end.z - start.z + ).normalize(); + + const perp = new THREE.Vector3(-direction.z, 0, direction.x).normalize(); + const offsetDistance = CONSTANTS.aisleConfig.width; + + const leftStart = new THREE.Vector3().copy(start).addScaledVector(perp, offsetDistance); + const rightStart = new THREE.Vector3().copy(start).addScaledVector(perp, -offsetDistance); + const leftEnd = new THREE.Vector3().copy(end).addScaledVector(perp, offsetDistance); + const rightEnd = new THREE.Vector3().copy(end).addScaledVector(perp, -offsetDistance); + + const stripShape = new THREE.Shape(); + stripShape.moveTo(leftStart.x, leftStart.z); + stripShape.lineTo(leftEnd.x, leftEnd.z); + stripShape.lineTo(rightEnd.x, rightEnd.z); + stripShape.lineTo(rightStart.x, rightStart.z); + stripShape.lineTo(leftStart.x, leftStart.z); + + const extrudeSettings = { + depth: CONSTANTS.aisleConfig.height, + bevelEnabled: false, + }; + + const stripGeometry = new THREE.ExtrudeGeometry(stripShape, extrudeSettings); + const stripMaterial = new THREE.MeshStandardMaterial({ + color: CONSTANTS.aisleConfig.defaultColor, + polygonOffset: true, + polygonOffsetFactor: -1, + polygonOffsetUnits: -1, + }); + + const stripMesh = new THREE.Mesh(stripGeometry, stripMaterial); + stripMesh.receiveShadow = true; + stripMesh.castShadow = true; + + stripMesh.position.y = (aisle[0][2] - 1) * CONSTANTS.wallConfig.height + 0.01; + stripMesh.rotateX(Math.PI / 2); + + floorGroupAisle.current.add(stripMesh); + } +} diff --git a/app/src/modules/builder/geomentries/aisles/loadAisles.ts b/app/src/modules/builder/geomentries/aisles/loadAisles.ts index cceacb8..437ae66 100644 --- a/app/src/modules/builder/geomentries/aisles/loadAisles.ts +++ b/app/src/modules/builder/geomentries/aisles/loadAisles.ts @@ -1,19 +1,19 @@ -import * as Types from '../../../../types/world/worldTypes'; -import addAisleToScene from './addAilseToScene'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; - -export default async function loadAisles( - lines: Types.RefLines, - floorGroupAisle: Types.RefGroup -) { - // console.log('lines: ', lines.current[0][0][0]); - if (!floorGroupAisle.current) return - floorGroupAisle.current.children = []; - const aisles = lines.current.filter((line) => line[0][3] && line[1][3] === CONSTANTS.lineConfig.aisleName); - - if (aisles.length > 0) { - aisles.forEach((aisle: Types.Line) => { - addAisleToScene(aisle, floorGroupAisle) - }) - } +import * as Types from '../../../../types/world/worldTypes'; +import addAisleToScene from './addAilseToScene'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; + +export default async function loadAisles( + lines: Types.RefLines, + floorGroupAisle: Types.RefGroup +) { + // console.log('lines: ', lines.current[0][0][0]); + if (!floorGroupAisle.current) return + floorGroupAisle.current.children = []; + const aisles = lines.current.filter((line) => line[0][3] && line[1][3] === CONSTANTS.lineConfig.aisleName); + + if (aisles.length > 0) { + aisles.forEach((aisle: Types.Line) => { + addAisleToScene(aisle, floorGroupAisle) + }) + } } \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/assets/addAssetModel.ts b/app/src/modules/builder/geomentries/assets/addAssetModel.ts index f211d38..e0e50c6 100644 --- a/app/src/modules/builder/geomentries/assets/addAssetModel.ts +++ b/app/src/modules/builder/geomentries/assets/addAssetModel.ts @@ -1,186 +1,186 @@ -import * as THREE from 'three'; -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; -import gsap from 'gsap'; -import { toast } from 'react-toastify'; -import TempLoader from './tempLoader'; -import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; -import * as Types from "../../../../types/world/worldTypes"; -import { retrieveGLTF, storeGLTF } from '../../../../utils/indexDB/idbUtils'; -// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; -import { Socket } from 'socket.io-client'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; - -async function addAssetModel( - raycaster: THREE.Raycaster, - camera: THREE.Camera, - pointer: THREE.Vector2, - floorGroup: Types.RefGroup, - setFloorItems: Types.setFloorItemSetState, - itemsGroup: Types.RefGroup, - isTempLoader: Types.RefBoolean, - tempLoader: Types.RefMesh, - socket: Socket, - selectedItem: any, - setSelectedItem: any, - plane: Types.RefMesh, -): Promise { - - ////////// Load Floor GLtf's and set the positions, rotation, type etc. in state and store in localstorage ////////// - - let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; - - try { - isTempLoader.current = true; - const loader = new GLTFLoader(); - const dracoLoader = new DRACOLoader(); - - dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); - loader.setDRACOLoader(dracoLoader); - - raycaster.setFromCamera(pointer, camera); - const floorIntersections = raycaster.intersectObjects(floorGroup.current.children, true); - const intersectedFloor = floorIntersections.find(intersect => intersect.object.name.includes("Floor")); - - const planeIntersections = raycaster.intersectObject(plane.current!, true); - const intersectedPlane = planeIntersections[0]; - - let intersectPoint: THREE.Vector3 | null = null; - - if (intersectedFloor && intersectedPlane) { - intersectPoint = intersectedFloor.distance < intersectedPlane.distance ? (new THREE.Vector3(intersectedFloor.point.x, Math.round(intersectedFloor.point.y), intersectedFloor.point.z)) : (new THREE.Vector3(intersectedPlane.point.x, 0, intersectedPlane.point.z)); - } else if (intersectedFloor) { - intersectPoint = new THREE.Vector3(intersectedFloor.point.x, Math.round(intersectedFloor.point.y), intersectedFloor.point.z); - } else if (intersectedPlane) { - intersectPoint = new THREE.Vector3(intersectedPlane.point.x, 0, intersectedPlane.point.z); - } - - if (intersectPoint) { - if (intersectPoint.y < 0) { - intersectPoint = new THREE.Vector3(intersectPoint.x, 0, intersectPoint.z); - } - const cachedModel = THREE.Cache.get(selectedItem.id); - if (cachedModel) { - // console.log(`[Cache] Fetching ${selectedItem.name}`); - handleModelLoad(cachedModel, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket); - return; - } else { - const cachedModelBlob = await retrieveGLTF(selectedItem.id); - - if (cachedModelBlob) { - // console.log(`Added ${selectedItem.name} from indexDB`); - - const blobUrl = URL.createObjectURL(cachedModelBlob); - loader.load(blobUrl, (gltf) => { - URL.revokeObjectURL(blobUrl); - THREE.Cache.remove(blobUrl); - THREE.Cache.add(selectedItem.id, gltf); - handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket); - }, - () => { - TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup); - }); - } else { - // console.log(`Added ${selectedItem.name} from Backend`); - - loader.load(`${url_Backend_dwinzo}/api/v1/AssetFile/${selectedItem.id}`, async (gltf) => { - const modelBlob = await fetch(`${url_Backend_dwinzo}/api/v1/AssetFile/${selectedItem.id}`).then((res) => res.blob()); - await storeGLTF(selectedItem.id, modelBlob); - THREE.Cache.add(selectedItem.id, gltf); - await handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket); - }, - () => { - TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup); - }); - } - } - } - } catch (error) { - console.error('Error fetching asset model:', error); - } finally { - setSelectedItem({}); - } -} - -async function handleModelLoad( - gltf: any, - intersectPoint: THREE.Vector3, - selectedItem: any, - itemsGroup: Types.RefGroup, - tempLoader: Types.RefMesh, - isTempLoader: Types.RefBoolean, - setFloorItems: Types.setFloorItemSetState, - socket: Socket -) { - const model = gltf.scene.clone(); - model.userData = { name: selectedItem.name, modelId: selectedItem.id }; - model.position.set(intersectPoint!.x, 3 + intersectPoint!.y, intersectPoint!.z); - model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); - - model.traverse((child: any) => { - if (child) { - child.castShadow = true; - child.receiveShadow = true; - } - }); - - itemsGroup.current.add(model); - if (tempLoader.current) { - (tempLoader.current.material).dispose(); - (tempLoader.current.geometry).dispose(); - itemsGroup.current.remove(tempLoader.current); - tempLoader.current = undefined; - } - - const newFloorItem: Types.FloorItemType = { - modeluuid: model.uuid, - modelname: selectedItem.name, - modelfileID: selectedItem.id, - position: [intersectPoint!.x, intersectPoint!.y, intersectPoint!.z], - rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z, }, - isLocked: false, - isVisible: true - }; - - setFloorItems((prevItems) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); - - const email = localStorage.getItem("email"); - const organization = email ? email.split("@")[1].split(".")[0] : "default"; - - //REST - - // await setFloorItemApi( - // organization, - // newFloorItem.modeluuid, - // newFloorItem.modelname, - // newFloorItem.position, - // { "x": model.rotation.x, "y": model.rotation.y, "z": model.rotation.z }, - // newFloorItem.modelfileID!, - // false, - // true, - // ); - - //SOCKET - - const data = { - organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, - modelfileID: newFloorItem.modelfileID, - position: newFloorItem.position, - rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z }, - isLocked: false, - isVisible: true, - socketId: socket.id, - }; - - socket.emit("v1:FloorItems:set", data); - - gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" }); - gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } }); -} - -export default addAssetModel; +import * as THREE from 'three'; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import gsap from 'gsap'; +import { toast } from 'react-toastify'; +import TempLoader from './tempLoader'; +import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; +import * as Types from "../../../../types/world/worldTypes"; +import { retrieveGLTF, storeGLTF } from '../../../../utils/indexDB/idbUtils'; +// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; +import { Socket } from 'socket.io-client'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; + +async function addAssetModel( + raycaster: THREE.Raycaster, + camera: THREE.Camera, + pointer: THREE.Vector2, + floorGroup: Types.RefGroup, + setFloorItems: Types.setFloorItemSetState, + itemsGroup: Types.RefGroup, + isTempLoader: Types.RefBoolean, + tempLoader: Types.RefMesh, + socket: Socket, + selectedItem: any, + setSelectedItem: any, + plane: Types.RefMesh, +): Promise { + + ////////// Load Floor GLtf's and set the positions, rotation, type etc. in state and store in localstorage ////////// + + let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; + + try { + isTempLoader.current = true; + const loader = new GLTFLoader(); + const dracoLoader = new DRACOLoader(); + + dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); + loader.setDRACOLoader(dracoLoader); + + raycaster.setFromCamera(pointer, camera); + const floorIntersections = raycaster.intersectObjects(floorGroup.current.children, true); + const intersectedFloor = floorIntersections.find(intersect => intersect.object.name.includes("Floor")); + + const planeIntersections = raycaster.intersectObject(plane.current!, true); + const intersectedPlane = planeIntersections[0]; + + let intersectPoint: THREE.Vector3 | null = null; + + if (intersectedFloor && intersectedPlane) { + intersectPoint = intersectedFloor.distance < intersectedPlane.distance ? (new THREE.Vector3(intersectedFloor.point.x, Math.round(intersectedFloor.point.y), intersectedFloor.point.z)) : (new THREE.Vector3(intersectedPlane.point.x, 0, intersectedPlane.point.z)); + } else if (intersectedFloor) { + intersectPoint = new THREE.Vector3(intersectedFloor.point.x, Math.round(intersectedFloor.point.y), intersectedFloor.point.z); + } else if (intersectedPlane) { + intersectPoint = new THREE.Vector3(intersectedPlane.point.x, 0, intersectedPlane.point.z); + } + + if (intersectPoint) { + if (intersectPoint.y < 0) { + intersectPoint = new THREE.Vector3(intersectPoint.x, 0, intersectPoint.z); + } + const cachedModel = THREE.Cache.get(selectedItem.id); + if (cachedModel) { + // console.log(`[Cache] Fetching ${selectedItem.name}`); + handleModelLoad(cachedModel, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket); + return; + } else { + const cachedModelBlob = await retrieveGLTF(selectedItem.id); + + if (cachedModelBlob) { + // console.log(`Added ${selectedItem.name} from indexDB`); + + const blobUrl = URL.createObjectURL(cachedModelBlob); + loader.load(blobUrl, (gltf) => { + URL.revokeObjectURL(blobUrl); + THREE.Cache.remove(blobUrl); + THREE.Cache.add(selectedItem.id, gltf); + handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket); + }, + () => { + TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup); + }); + } else { + // console.log(`Added ${selectedItem.name} from Backend`); + + loader.load(`${url_Backend_dwinzo}/api/v1/AssetFile/${selectedItem.id}`, async (gltf) => { + const modelBlob = await fetch(`${url_Backend_dwinzo}/api/v1/AssetFile/${selectedItem.id}`).then((res) => res.blob()); + await storeGLTF(selectedItem.id, modelBlob); + THREE.Cache.add(selectedItem.id, gltf); + await handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket); + }, + () => { + TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup); + }); + } + } + } + } catch (error) { + console.error('Error fetching asset model:', error); + } finally { + setSelectedItem({}); + } +} + +async function handleModelLoad( + gltf: any, + intersectPoint: THREE.Vector3, + selectedItem: any, + itemsGroup: Types.RefGroup, + tempLoader: Types.RefMesh, + isTempLoader: Types.RefBoolean, + setFloorItems: Types.setFloorItemSetState, + socket: Socket +) { + const model = gltf.scene.clone(); + model.userData = { name: selectedItem.name, modelId: selectedItem.id }; + model.position.set(intersectPoint!.x, 3 + intersectPoint!.y, intersectPoint!.z); + model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); + + model.traverse((child: any) => { + if (child) { + child.castShadow = true; + child.receiveShadow = true; + } + }); + + itemsGroup.current.add(model); + if (tempLoader.current) { + (tempLoader.current.material).dispose(); + (tempLoader.current.geometry).dispose(); + itemsGroup.current.remove(tempLoader.current); + tempLoader.current = undefined; + } + + const newFloorItem: Types.FloorItemType = { + modeluuid: model.uuid, + modelname: selectedItem.name, + modelfileID: selectedItem.id, + position: [intersectPoint!.x, intersectPoint!.y, intersectPoint!.z], + rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z, }, + isLocked: false, + isVisible: true + }; + + setFloorItems((prevItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + const email = localStorage.getItem("email"); + const organization = email ? email.split("@")[1].split(".")[0] : "default"; + + //REST + + // await setFloorItemApi( + // organization, + // newFloorItem.modeluuid, + // newFloorItem.modelname, + // newFloorItem.position, + // { "x": model.rotation.x, "y": model.rotation.y, "z": model.rotation.z }, + // newFloorItem.modelfileID!, + // false, + // true, + // ); + + //SOCKET + + const data = { + organization, + modeluuid: newFloorItem.modeluuid, + modelname: newFloorItem.modelname, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id, + }; + + socket.emit("v1:FloorItems:set", data); + + gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" }); + gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } }); +} + +export default addAssetModel; diff --git a/app/src/modules/builder/geomentries/assets/assetManager.ts b/app/src/modules/builder/geomentries/assets/assetManager.ts index 837c4d3..f083395 100644 --- a/app/src/modules/builder/geomentries/assets/assetManager.ts +++ b/app/src/modules/builder/geomentries/assets/assetManager.ts @@ -1,153 +1,153 @@ -import * as THREE from "three"; -import gsap from "gsap"; -import * as Types from "../../../../types/world/worldTypes"; -import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; -import { initializeDB, retrieveGLTF, storeGLTF } from "../../../../utils/indexDB/idbUtils"; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -import { toast } from 'react-toastify'; - -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; -let currentTaskId = 0; // Track the active task -let activePromises = new Map(); // Map to track task progress - -export default async function assetManager( - data: any, - itemsGroup: Types.RefGroup, - loader: GLTFLoader, -) { - const taskId = ++currentTaskId; // Increment taskId for each call - activePromises.set(taskId, true); // Mark task as active - - // console.log("Received message from worker:", data); - - if (data.toRemove.length > 0) { - data.toRemove.forEach((uuid: string) => { - const item = itemsGroup.current.getObjectByProperty("uuid", uuid); - if (item) { - // Traverse and dispose of resources - // item.traverse((child: THREE.Object3D) => { - // if (child instanceof THREE.Mesh) { - // if (child.geometry) child.geometry.dispose(); - // if (Array.isArray(child.material)) { - // child.material.forEach((material) => { - // if (material.map) material.map.dispose(); - // material.dispose(); - // }); - // } else if (child.material) { - // if (child.material.map) child.material.map.dispose(); - // child.material.dispose(); - // } - // } - // }); - - // Remove the object from the scene - itemsGroup.current.remove(item); - } - }); - } - - if (data.toAdd.length > 0) { - await initializeDB(); - - for (const item of data.toAdd) { - if (!activePromises.get(taskId)) return; // Stop processing if task is canceled - - await new Promise(async (resolve) => { - const modelUrl = `${url_Backend_dwinzo}/api/v1/AssetFile/${item.modelfileID!}`; - - // Check Three.js Cache - const cachedModel = THREE.Cache.get(item.modelfileID!); - if (cachedModel) { - // console.log(`[Cache] Fetching ${item.modelname}`); - processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, resolve); - return; - } - - // Check IndexedDB - const indexedDBModel = await retrieveGLTF(item.modelfileID!); - if (indexedDBModel) { - // console.log(`[IndexedDB] Fetching ${item.modelname}`); - const blobUrl = URL.createObjectURL(indexedDBModel); - loader.load( - blobUrl, - (gltf) => { - URL.revokeObjectURL(blobUrl); - THREE.Cache.remove(blobUrl); - THREE.Cache.add(item.modelfileID!, gltf); // Add to cache - processLoadedModel(gltf.scene.clone(), item, itemsGroup, resolve); - }, - undefined, - (error) => { - toast.error(`[IndexedDB] Error loading ${item.modelname}:`); - resolve(); - } - ); - return; - } - - // Fetch from Backend - // console.log(`[Backend] Fetching ${item.modelname}`); - loader.load( - modelUrl, - async (gltf) => { - const modelBlob = await fetch(modelUrl).then((res) => res.blob()); - await storeGLTF(item.modelfileID!, modelBlob); // Store in IndexedDB - THREE.Cache.add(item.modelfileID!, gltf); // Add to cache - processLoadedModel(gltf.scene.clone(), item, itemsGroup, resolve); - }, - undefined, - (error) => { - toast.error(`[Backend] Error loading ${item.modelname}:`); - resolve(); - } - ); - }); - } - - function processLoadedModel( - gltf: any, - item: Types.FloorItemType, - itemsGroup: Types.RefGroup, - resolve: () => void - ) { - if (!activePromises.get(taskId)) return; // Stop processing if task is canceled - - const existingModel = itemsGroup.current.getObjectByProperty("uuid", item.modeluuid); - if (existingModel) { - // console.log(`Model ${item.modelname} already exists in the scene.`); - resolve(); - return; - } - - const model = gltf; - model.uuid = item.modeluuid; - model.userData = { name: item.modelname, modelId: item.modelfileID }; - model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); - model.position.set(...item.position); - model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z); - - model.traverse((child: any) => { - if (child.isMesh) { - // Clone the material to ensure changes are independent - // child.material = child.material.clone(); - - child.castShadow = true; - child.receiveShadow = true; - } - }); - - - itemsGroup?.current?.add(model); - - gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: "power2.out" }); - gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 0.5, ease: "power2.out", onStart: resolve, }); - } - } - - activePromises.delete(taskId); // Mark task as complete -} - -// Cancel ongoing task when new call arrives -export function cancelOngoingTasks() { - activePromises.clear(); // Clear all ongoing tasks -} +import * as THREE from "three"; +import gsap from "gsap"; +import * as Types from "../../../../types/world/worldTypes"; +import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; +import { initializeDB, retrieveGLTF, storeGLTF } from "../../../../utils/indexDB/idbUtils"; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +import { toast } from 'react-toastify'; + +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; +let currentTaskId = 0; // Track the active task +let activePromises = new Map(); // Map to track task progress + +export default async function assetManager( + data: any, + itemsGroup: Types.RefGroup, + loader: GLTFLoader, +) { + const taskId = ++currentTaskId; // Increment taskId for each call + activePromises.set(taskId, true); // Mark task as active + + // console.log("Received message from worker:", data); + + if (data.toRemove.length > 0) { + data.toRemove.forEach((uuid: string) => { + const item = itemsGroup.current.getObjectByProperty("uuid", uuid); + if (item) { + // Traverse and dispose of resources + // item.traverse((child: THREE.Object3D) => { + // if (child instanceof THREE.Mesh) { + // if (child.geometry) child.geometry.dispose(); + // if (Array.isArray(child.material)) { + // child.material.forEach((material) => { + // if (material.map) material.map.dispose(); + // material.dispose(); + // }); + // } else if (child.material) { + // if (child.material.map) child.material.map.dispose(); + // child.material.dispose(); + // } + // } + // }); + + // Remove the object from the scene + itemsGroup.current.remove(item); + } + }); + } + + if (data.toAdd.length > 0) { + await initializeDB(); + + for (const item of data.toAdd) { + if (!activePromises.get(taskId)) return; // Stop processing if task is canceled + + await new Promise(async (resolve) => { + const modelUrl = `${url_Backend_dwinzo}/api/v1/AssetFile/${item.modelfileID!}`; + + // Check Three.js Cache + const cachedModel = THREE.Cache.get(item.modelfileID!); + if (cachedModel) { + // console.log(`[Cache] Fetching ${item.modelname}`); + processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, resolve); + return; + } + + // Check IndexedDB + const indexedDBModel = await retrieveGLTF(item.modelfileID!); + if (indexedDBModel) { + // console.log(`[IndexedDB] Fetching ${item.modelname}`); + const blobUrl = URL.createObjectURL(indexedDBModel); + loader.load( + blobUrl, + (gltf) => { + URL.revokeObjectURL(blobUrl); + THREE.Cache.remove(blobUrl); + THREE.Cache.add(item.modelfileID!, gltf); // Add to cache + processLoadedModel(gltf.scene.clone(), item, itemsGroup, resolve); + }, + undefined, + (error) => { + toast.error(`[IndexedDB] Error loading ${item.modelname}:`); + resolve(); + } + ); + return; + } + + // Fetch from Backend + // console.log(`[Backend] Fetching ${item.modelname}`); + loader.load( + modelUrl, + async (gltf) => { + const modelBlob = await fetch(modelUrl).then((res) => res.blob()); + await storeGLTF(item.modelfileID!, modelBlob); // Store in IndexedDB + THREE.Cache.add(item.modelfileID!, gltf); // Add to cache + processLoadedModel(gltf.scene.clone(), item, itemsGroup, resolve); + }, + undefined, + (error) => { + toast.error(`[Backend] Error loading ${item.modelname}:`); + resolve(); + } + ); + }); + } + + function processLoadedModel( + gltf: any, + item: Types.FloorItemType, + itemsGroup: Types.RefGroup, + resolve: () => void + ) { + if (!activePromises.get(taskId)) return; // Stop processing if task is canceled + + const existingModel = itemsGroup.current.getObjectByProperty("uuid", item.modeluuid); + if (existingModel) { + // console.log(`Model ${item.modelname} already exists in the scene.`); + resolve(); + return; + } + + const model = gltf; + model.uuid = item.modeluuid; + model.userData = { name: item.modelname, modelId: item.modelfileID }; + model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); + model.position.set(...item.position); + model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z); + + model.traverse((child: any) => { + if (child.isMesh) { + // Clone the material to ensure changes are independent + // child.material = child.material.clone(); + + child.castShadow = true; + child.receiveShadow = true; + } + }); + + + itemsGroup?.current?.add(model); + + gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: "power2.out" }); + gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 0.5, ease: "power2.out", onStart: resolve, }); + } + } + + activePromises.delete(taskId); // Mark task as complete +} + +// Cancel ongoing task when new call arrives +export function cancelOngoingTasks() { + activePromises.clear(); // Clear all ongoing tasks +} diff --git a/app/src/modules/builder/geomentries/assets/assetVisibility.ts b/app/src/modules/builder/geomentries/assets/assetVisibility.ts index e2778f6..c2503c3 100644 --- a/app/src/modules/builder/geomentries/assets/assetVisibility.ts +++ b/app/src/modules/builder/geomentries/assets/assetVisibility.ts @@ -1,25 +1,25 @@ -import * as Types from "../../../../types/world/worldTypes"; - -let lastUpdateTime = 0; - -export default function assetVisibility( - itemsGroup: Types.RefGroup, - cameraPosition: Types.Vector3, - renderDistance: Types.Number, - throttleTime = 100 -): void { - const now = performance.now(); - if (now - lastUpdateTime < throttleTime) return; - lastUpdateTime = now; - - if (!itemsGroup?.current || !cameraPosition) return; - - itemsGroup.current.children.forEach((child) => { - const Distance = cameraPosition.distanceTo(child.position); - if (Distance <= renderDistance) { - child.visible = true; - } else { - child.visible = false; - } - }); -} +import * as Types from "../../../../types/world/worldTypes"; + +let lastUpdateTime = 0; + +export default function assetVisibility( + itemsGroup: Types.RefGroup, + cameraPosition: Types.Vector3, + renderDistance: Types.Number, + throttleTime = 100 +): void { + const now = performance.now(); + if (now - lastUpdateTime < throttleTime) return; + lastUpdateTime = now; + + if (!itemsGroup?.current || !cameraPosition) return; + + itemsGroup.current.children.forEach((child) => { + const Distance = cameraPosition.distanceTo(child.position); + if (Distance <= renderDistance) { + child.visible = true; + } else { + child.visible = false; + } + }); +} diff --git a/app/src/modules/builder/geomentries/assets/deletableHoveredFloorItems.ts b/app/src/modules/builder/geomentries/assets/deletableHoveredFloorItems.ts index 9af432e..2913b1a 100644 --- a/app/src/modules/builder/geomentries/assets/deletableHoveredFloorItems.ts +++ b/app/src/modules/builder/geomentries/assets/deletableHoveredFloorItems.ts @@ -1,43 +1,43 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; - -function DeletableHoveredFloorItems( - state: Types.ThreeState, - itemsGroup: Types.RefGroup, - hoveredDeletableFloorItem: Types.RefMesh, - setDeletableFloorItem: any -): void { - - ////////// Altering the color of the hovered GLTF item during the Deletion time ////////// - - state.raycaster.setFromCamera(state.pointer, state.camera); - const intersects = state.raycaster.intersectObjects(itemsGroup.current.children, true); - - if (intersects.length > 0) { - if (intersects[0].object.name === "Pole") { - return; - } - if (hoveredDeletableFloorItem.current) { - hoveredDeletableFloorItem.current = undefined; - setDeletableFloorItem(null); - } - let currentObject = intersects[0].object; - - while (currentObject) { - if (currentObject.name === "Scene") { - hoveredDeletableFloorItem.current = currentObject as THREE.Mesh; - setDeletableFloorItem(currentObject); - break; - } - currentObject = currentObject.parent as THREE.Object3D; - } - } else { - if (hoveredDeletableFloorItem.current) { - hoveredDeletableFloorItem.current = undefined; - setDeletableFloorItem(null); - } - } -} - -export default DeletableHoveredFloorItems; +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; + +function DeletableHoveredFloorItems( + state: Types.ThreeState, + itemsGroup: Types.RefGroup, + hoveredDeletableFloorItem: Types.RefMesh, + setDeletableFloorItem: any +): void { + + ////////// Altering the color of the hovered GLTF item during the Deletion time ////////// + + state.raycaster.setFromCamera(state.pointer, state.camera); + const intersects = state.raycaster.intersectObjects(itemsGroup.current.children, true); + + if (intersects.length > 0) { + if (intersects[0].object.name === "Pole") { + return; + } + if (hoveredDeletableFloorItem.current) { + hoveredDeletableFloorItem.current = undefined; + setDeletableFloorItem(null); + } + let currentObject = intersects[0].object; + + while (currentObject) { + if (currentObject.name === "Scene") { + hoveredDeletableFloorItem.current = currentObject as THREE.Mesh; + setDeletableFloorItem(currentObject); + break; + } + currentObject = currentObject.parent as THREE.Object3D; + } + } else { + if (hoveredDeletableFloorItem.current) { + hoveredDeletableFloorItem.current = undefined; + setDeletableFloorItem(null); + } + } +} + +export default DeletableHoveredFloorItems; diff --git a/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts b/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts index 65d5493..87930dc 100644 --- a/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts +++ b/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts @@ -1,82 +1,82 @@ -import { toast } from 'react-toastify'; -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; -import { getFloorItems } from '../../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi'; -// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi'; -import { Socket } from 'socket.io-client'; - -async function DeleteFloorItems( - itemsGroup: Types.RefGroup, - hoveredDeletableFloorItem: Types.RefMesh, - setFloorItems: Types.setFloorItemSetState, - socket: Socket -): Promise { - - ////////// Deleting the hovered Floor GLTF from the scene (itemsGroup.current) and from the floorItems and also update it in the localstorage ////////// - - if (hoveredDeletableFloorItem.current) { - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - const items = await getFloorItems(organization); - const removedItem = items.find( - (item: { modeluuid: string }) => item.modeluuid === hoveredDeletableFloorItem.current?.uuid - ); - - if (!removedItem) { - return - } - - //REST - - // const response = await deleteFloorItem(organization, removedItem.modeluuid, removedItem.modelname); - - //SOCKET - - const data = { - organization: organization, - modeluuid: removedItem.modeluuid, - modelname: removedItem.modelname, - socketId: socket.id - } - - const response = socket.emit('v1:FloorItems:delete', data) - - if (response) { - const updatedItems = items.filter( - (item: { modeluuid: string }) => item.modeluuid !== hoveredDeletableFloorItem.current?.uuid - ); - - const storedItems = JSON.parse(localStorage.getItem("FloorItems") || '[]'); - const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => item.modeluuid !== hoveredDeletableFloorItem.current?.uuid); - localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); - - if (hoveredDeletableFloorItem.current) { - // Traverse and dispose of resources - hoveredDeletableFloorItem.current.traverse((child: THREE.Object3D) => { - if (child instanceof THREE.Mesh) { - if (child.geometry) child.geometry.dispose(); - if (Array.isArray(child.material)) { - child.material.forEach((material) => { - if (material.map) material.map.dispose(); - material.dispose(); - }); - } else if (child.material) { - if (child.material.map) child.material.map.dispose(); - child.material.dispose(); - } - } - }); - - // Remove the object from the scene - itemsGroup.current.remove(hoveredDeletableFloorItem.current); - } - setFloorItems(updatedItems); - toast.success("Model Removed!"); - } - } -} - -export default DeleteFloorItems; +import { toast } from 'react-toastify'; +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; +import { getFloorItems } from '../../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi'; +// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi'; +import { Socket } from 'socket.io-client'; + +async function DeleteFloorItems( + itemsGroup: Types.RefGroup, + hoveredDeletableFloorItem: Types.RefMesh, + setFloorItems: Types.setFloorItemSetState, + socket: Socket +): Promise { + + ////////// Deleting the hovered Floor GLTF from the scene (itemsGroup.current) and from the floorItems and also update it in the localstorage ////////// + + if (hoveredDeletableFloorItem.current) { + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + const items = await getFloorItems(organization); + const removedItem = items.find( + (item: { modeluuid: string }) => item.modeluuid === hoveredDeletableFloorItem.current?.uuid + ); + + if (!removedItem) { + return + } + + //REST + + // const response = await deleteFloorItem(organization, removedItem.modeluuid, removedItem.modelname); + + //SOCKET + + const data = { + organization: organization, + modeluuid: removedItem.modeluuid, + modelname: removedItem.modelname, + socketId: socket.id + } + + const response = socket.emit('v1:FloorItems:delete', data) + + if (response) { + const updatedItems = items.filter( + (item: { modeluuid: string }) => item.modeluuid !== hoveredDeletableFloorItem.current?.uuid + ); + + const storedItems = JSON.parse(localStorage.getItem("FloorItems") || '[]'); + const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => item.modeluuid !== hoveredDeletableFloorItem.current?.uuid); + localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); + + if (hoveredDeletableFloorItem.current) { + // Traverse and dispose of resources + hoveredDeletableFloorItem.current.traverse((child: THREE.Object3D) => { + if (child instanceof THREE.Mesh) { + if (child.geometry) child.geometry.dispose(); + if (Array.isArray(child.material)) { + child.material.forEach((material) => { + if (material.map) material.map.dispose(); + material.dispose(); + }); + } else if (child.material) { + if (child.material.map) child.material.map.dispose(); + child.material.dispose(); + } + } + }); + + // Remove the object from the scene + itemsGroup.current.remove(hoveredDeletableFloorItem.current); + } + setFloorItems(updatedItems); + toast.success("Model Removed!"); + } + } +} + +export default DeleteFloorItems; diff --git a/app/src/modules/builder/geomentries/assets/tempLoader.ts b/app/src/modules/builder/geomentries/assets/tempLoader.ts index 601b60a..73d2f9e 100644 --- a/app/src/modules/builder/geomentries/assets/tempLoader.ts +++ b/app/src/modules/builder/geomentries/assets/tempLoader.ts @@ -1,29 +1,29 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; - -function TempLoader( - intersectPoint: Types.Vector3, - isTempLoader: Types.RefBoolean, - tempLoader: Types.RefMesh, - itemsGroup: Types.RefGroup -): void { - - ////////// Temporary Loader that indicates the gltf is being loaded ////////// - - ////////// Bug: Can't Load More than one TempLoader if done, it won't leave the scene ////////// - - if (tempLoader.current) { - itemsGroup.current.remove(tempLoader.current); - } - if (isTempLoader.current) { - const cubeGeometry = new THREE.BoxGeometry(1, 1, 1); - const cubeMaterial = new THREE.MeshBasicMaterial({ color: "white" }); - tempLoader.current = new THREE.Mesh(cubeGeometry, cubeMaterial); - tempLoader.current.position.set(intersectPoint.x, 0.5 + intersectPoint.y, intersectPoint.z); - itemsGroup.current.add(tempLoader.current); - isTempLoader.current = false; - } -} - -export default TempLoader; +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; + +function TempLoader( + intersectPoint: Types.Vector3, + isTempLoader: Types.RefBoolean, + tempLoader: Types.RefMesh, + itemsGroup: Types.RefGroup +): void { + + ////////// Temporary Loader that indicates the gltf is being loaded ////////// + + ////////// Bug: Can't Load More than one TempLoader if done, it won't leave the scene ////////// + + if (tempLoader.current) { + itemsGroup.current.remove(tempLoader.current); + } + if (isTempLoader.current) { + const cubeGeometry = new THREE.BoxGeometry(1, 1, 1); + const cubeMaterial = new THREE.MeshBasicMaterial({ color: "white" }); + tempLoader.current = new THREE.Mesh(cubeGeometry, cubeMaterial); + tempLoader.current.position.set(intersectPoint.x, 0.5 + intersectPoint.y, intersectPoint.z); + itemsGroup.current.add(tempLoader.current); + isTempLoader.current = false; + } +} + +export default TempLoader; diff --git a/app/src/modules/builder/geomentries/floors/addFloorToScene.ts b/app/src/modules/builder/geomentries/floors/addFloorToScene.ts index acf738b..e2f0baa 100644 --- a/app/src/modules/builder/geomentries/floors/addFloorToScene.ts +++ b/app/src/modules/builder/geomentries/floors/addFloorToScene.ts @@ -1,64 +1,64 @@ -import * as THREE from 'three'; -import * as Types from "../../../../types/world/worldTypes"; -import * as CONSTANTS from "../../../../types/world/worldConstants"; - -import texturePath from "../../../../assets/textures/floor/concreteFloorWorn001Diff2k.jpg"; -import normalPath from "../../../../assets/textures/floor/concreteFloorWorn001NorGl2k.jpg"; - -// Cache for materials -const materialCache = new Map(); - -export default function addFloorToScene( - shape: THREE.Shape, - layer: number, - floorGroup: Types.RefGroup, - userData: any, -) { - const textureLoader = new THREE.TextureLoader(); - - const textureScale = CONSTANTS.floorConfig.textureScale; - - const materialKey = `floorMaterial_${textureScale}`; - - let material: THREE.Material; - - if (materialCache.has(materialKey)) { - material = materialCache.get(materialKey) as THREE.Material; - } else { - const floorTexture = textureLoader.load(texturePath); - const normalMap = textureLoader.load(normalPath); - - floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping; - floorTexture.repeat.set(textureScale, textureScale); - floorTexture.colorSpace = THREE.SRGBColorSpace; - - normalMap.wrapS = normalMap.wrapT = THREE.RepeatWrapping; - normalMap.repeat.set(textureScale, textureScale); - - material = new THREE.MeshStandardMaterial({ - map: floorTexture, - normalMap: normalMap, - side: THREE.DoubleSide, - }); - - materialCache.set(materialKey, material); - } - - const extrudeSettings = { - depth: CONSTANTS.floorConfig.height, - bevelEnabled: false, - }; - - const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); - const mesh = new THREE.Mesh(geometry, material); - - mesh.receiveShadow = true; - mesh.position.y = layer; - mesh.rotateX(Math.PI / 2); - mesh.name = `Floor_Layer_${layer}`; - - // Store UUIDs for debugging or future processing - mesh.userData.uuids = userData; - - floorGroup.current.add(mesh); -} +import * as THREE from 'three'; +import * as Types from "../../../../types/world/worldTypes"; +import * as CONSTANTS from "../../../../types/world/worldConstants"; + +import texturePath from "../../../../assets/textures/floor/concreteFloorWorn001Diff2k.jpg"; +import normalPath from "../../../../assets/textures/floor/concreteFloorWorn001NorGl2k.jpg"; + +// Cache for materials +const materialCache = new Map(); + +export default function addFloorToScene( + shape: THREE.Shape, + layer: number, + floorGroup: Types.RefGroup, + userData: any, +) { + const textureLoader = new THREE.TextureLoader(); + + const textureScale = CONSTANTS.floorConfig.textureScale; + + const materialKey = `floorMaterial_${textureScale}`; + + let material: THREE.Material; + + if (materialCache.has(materialKey)) { + material = materialCache.get(materialKey) as THREE.Material; + } else { + const floorTexture = textureLoader.load(texturePath); + const normalMap = textureLoader.load(normalPath); + + floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping; + floorTexture.repeat.set(textureScale, textureScale); + floorTexture.colorSpace = THREE.SRGBColorSpace; + + normalMap.wrapS = normalMap.wrapT = THREE.RepeatWrapping; + normalMap.repeat.set(textureScale, textureScale); + + material = new THREE.MeshStandardMaterial({ + map: floorTexture, + normalMap: normalMap, + side: THREE.DoubleSide, + }); + + materialCache.set(materialKey, material); + } + + const extrudeSettings = { + depth: CONSTANTS.floorConfig.height, + bevelEnabled: false, + }; + + const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); + const mesh = new THREE.Mesh(geometry, material); + + mesh.receiveShadow = true; + mesh.position.y = layer; + mesh.rotateX(Math.PI / 2); + mesh.name = `Floor_Layer_${layer}`; + + // Store UUIDs for debugging or future processing + mesh.userData.uuids = userData; + + floorGroup.current.add(mesh); +} diff --git a/app/src/modules/builder/geomentries/floors/drawOnlyFloor.ts b/app/src/modules/builder/geomentries/floors/drawOnlyFloor.ts index 90f291e..ebe0eb4 100644 --- a/app/src/modules/builder/geomentries/floors/drawOnlyFloor.ts +++ b/app/src/modules/builder/geomentries/floors/drawOnlyFloor.ts @@ -1,179 +1,179 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; -import * as CONSTANTS from '../../../../types/world/worldConstants'; - -import addPointToScene from '../points/addPointToScene'; -import addLineToScene from '../lines/addLineToScene'; -import splitLine from '../lines/splitLine'; -import removeReferenceLine from '../lines/removeReferenceLine'; -import getClosestIntersection from '../lines/getClosestIntersection'; -import arrayLineToObject from '../lines/lineConvertions/arrayLineToObject'; -// import { setLine } from '../../../../services/factoryBuilder/lines/setLineApi'; -import { Socket } from 'socket.io-client'; - -async function drawOnlyFloor( - raycaster: THREE.Raycaster, - state: Types.ThreeState, - camera: THREE.Camera, - plane: Types.RefMesh, - floorPlanGroupPoint: Types.RefGroup, - snappedPoint: Types.RefVector3, - isSnapped: Types.RefBoolean, - isSnappedUUID: Types.RefString, - line: Types.RefLine, - ispreSnapped: Types.RefBoolean, - anglesnappedPoint: Types.RefVector3, - isAngleSnapped: Types.RefBoolean, - onlyFloorline: Types.RefOnlyFloorLine, - onlyFloorlines: Types.RefOnlyFloorLines, - lines: Types.RefLines, - floorPlanGroupLine: Types.RefGroup, - floorPlanGroup: Types.RefGroup, - ReferenceLineMesh: Types.RefMesh, - LineCreated: Types.RefBoolean, - currentLayerPoint: Types.RefMeshArray, - dragPointControls: Types.RefDragControl, - setNewLines: any, - setDeletedLines: any, - activeLayer: Types.Number, - socket: Socket -): Promise { - - ////////// Creating lines Based on the positions clicked ////////// - - if (!plane.current) return - const intersects = raycaster.intersectObject(plane.current, true); - const intersectsLines = raycaster.intersectObjects(floorPlanGroupLine.current.children, true); - const intersectsPoint = raycaster.intersectObjects(floorPlanGroupPoint.current.children, true); - const VisibleintersectsPoint = intersectsPoint.find(intersect => intersect.object.visible); - const visibleIntersect = intersectsLines.find(intersect => intersect.object.visible && intersect.object.name !== CONSTANTS.lineConfig.referenceName); - - if ((intersectsPoint.length === 0 || VisibleintersectsPoint === undefined) && intersectsLines.length > 0 && !isSnapped.current && !ispreSnapped.current) { - - ////////// Clicked on a preexisting Line ////////// - - if (visibleIntersect && (intersectsLines[0].object.userData.linePoints[0][3] === CONSTANTS.lineConfig.floorName || intersectsLines[0].object.userData.linePoints[0][3] === CONSTANTS.lineConfig.wallName)) { - let pointColor, lineColor; - if (intersectsLines[0].object.userData.linePoints[0][3] === CONSTANTS.lineConfig.wallName) { - pointColor = CONSTANTS.pointConfig.wallOuterColor; - lineColor = CONSTANTS.lineConfig.wallColor; - } else { - pointColor = CONSTANTS.pointConfig.floorOuterColor; - lineColor = CONSTANTS.lineConfig.floorColor; - } - let IntersectsPoint = new THREE.Vector3(intersects[0].point.x, 0.01, intersects[0].point.z); - if (isAngleSnapped.current && line.current.length > 0 && anglesnappedPoint.current) { - IntersectsPoint = anglesnappedPoint.current; - } - if (visibleIntersect.object instanceof THREE.Mesh) { - const ThroughPoint = (visibleIntersect.object.geometry.parameters.path).getPoints(CONSTANTS.lineConfig.lineIntersectionPoints); - let intersectionPoint = getClosestIntersection(ThroughPoint, IntersectsPoint); - - if (intersectionPoint) { - - const newLines = splitLine(visibleIntersect, intersectionPoint, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, lines, setDeletedLines, floorPlanGroupLine, socket, pointColor, lineColor, intersectsLines[0].object.userData.linePoints[0][3]); - setNewLines([newLines[0], newLines[1]]); - - (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), isSnappedUUID.current!, activeLayer, CONSTANTS.lineConfig.floorName]); - - if (line.current.length >= 2 && line.current[0] && line.current[1]) { - lines.current.push(line.current as Types.Line); - const data = arrayLineToObject(line.current as Types.Line); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setLine(organization, data.layer!, data.line!, data.type!); - - //SOCKET - - const input = { - organization: organization, - layer: data.layer, - line: data.line, - type: data.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input); - - setNewLines([newLines[0], newLines[1], line.current]); - onlyFloorline.current.push(line.current as Types.Line); - onlyFloorlines.current.push(onlyFloorline.current); - onlyFloorline.current = []; - - addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.floorColor, line.current, floorPlanGroupLine); - - removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); - } - return; - } - } - } - } - if (intersects.length > 0 && intersectsLines.length === 0) { - - ////////// Clicked on an empty place or a point ////////// - - let intersectionPoint = intersects[0].point; - - if (isAngleSnapped.current && line.current.length > 0 && anglesnappedPoint.current) { - intersectionPoint = anglesnappedPoint.current; - } - if (isSnapped.current && line.current.length > 0 && snappedPoint.current) { - intersectionPoint = snappedPoint.current; - } - if (ispreSnapped.current && snappedPoint.current) { - intersectionPoint = snappedPoint.current; - } - - if (!isSnapped.current && !ispreSnapped.current) { - addPointToScene(intersectionPoint, CONSTANTS.pointConfig.floorOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, CONSTANTS.lineConfig.floorName); - } else { - ispreSnapped.current = false; - isSnapped.current = false; - } - - (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), isSnappedUUID.current!, activeLayer, CONSTANTS.lineConfig.floorName]); - - if (line.current.length >= 2 && line.current[0] && line.current[1]) { - onlyFloorline.current.push(line.current as Types.Line); - lines.current.push(line.current as Types.Line); - const data = arrayLineToObject(line.current as Types.Line); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setLine(organization, data.layer!, data.line!, data.type!); - - //SOCKET - - const input = { - organization: organization, - layer: data.layer, - line: data.line, - type: data.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input); - - setNewLines([line.current]); - addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.floorColor, line.current, floorPlanGroupLine); - const lastPoint = line.current[line.current.length - 1]; - line.current = [lastPoint]; - } - if (isSnapped.current) { ////////// Add this to stop the drawing mode after snapping ////////// - removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); - onlyFloorlines.current.push(onlyFloorline.current); - onlyFloorline.current = []; - } - } -} - +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; +import * as CONSTANTS from '../../../../types/world/worldConstants'; + +import addPointToScene from '../points/addPointToScene'; +import addLineToScene from '../lines/addLineToScene'; +import splitLine from '../lines/splitLine'; +import removeReferenceLine from '../lines/removeReferenceLine'; +import getClosestIntersection from '../lines/getClosestIntersection'; +import arrayLineToObject from '../lines/lineConvertions/arrayLineToObject'; +// import { setLine } from '../../../../services/factoryBuilder/lines/setLineApi'; +import { Socket } from 'socket.io-client'; + +async function drawOnlyFloor( + raycaster: THREE.Raycaster, + state: Types.ThreeState, + camera: THREE.Camera, + plane: Types.RefMesh, + floorPlanGroupPoint: Types.RefGroup, + snappedPoint: Types.RefVector3, + isSnapped: Types.RefBoolean, + isSnappedUUID: Types.RefString, + line: Types.RefLine, + ispreSnapped: Types.RefBoolean, + anglesnappedPoint: Types.RefVector3, + isAngleSnapped: Types.RefBoolean, + onlyFloorline: Types.RefOnlyFloorLine, + onlyFloorlines: Types.RefOnlyFloorLines, + lines: Types.RefLines, + floorPlanGroupLine: Types.RefGroup, + floorPlanGroup: Types.RefGroup, + ReferenceLineMesh: Types.RefMesh, + LineCreated: Types.RefBoolean, + currentLayerPoint: Types.RefMeshArray, + dragPointControls: Types.RefDragControl, + setNewLines: any, + setDeletedLines: any, + activeLayer: Types.Number, + socket: Socket +): Promise { + + ////////// Creating lines Based on the positions clicked ////////// + + if (!plane.current) return + const intersects = raycaster.intersectObject(plane.current, true); + const intersectsLines = raycaster.intersectObjects(floorPlanGroupLine.current.children, true); + const intersectsPoint = raycaster.intersectObjects(floorPlanGroupPoint.current.children, true); + const VisibleintersectsPoint = intersectsPoint.find(intersect => intersect.object.visible); + const visibleIntersect = intersectsLines.find(intersect => intersect.object.visible && intersect.object.name !== CONSTANTS.lineConfig.referenceName); + + if ((intersectsPoint.length === 0 || VisibleintersectsPoint === undefined) && intersectsLines.length > 0 && !isSnapped.current && !ispreSnapped.current) { + + ////////// Clicked on a preexisting Line ////////// + + if (visibleIntersect && (intersectsLines[0].object.userData.linePoints[0][3] === CONSTANTS.lineConfig.floorName || intersectsLines[0].object.userData.linePoints[0][3] === CONSTANTS.lineConfig.wallName)) { + let pointColor, lineColor; + if (intersectsLines[0].object.userData.linePoints[0][3] === CONSTANTS.lineConfig.wallName) { + pointColor = CONSTANTS.pointConfig.wallOuterColor; + lineColor = CONSTANTS.lineConfig.wallColor; + } else { + pointColor = CONSTANTS.pointConfig.floorOuterColor; + lineColor = CONSTANTS.lineConfig.floorColor; + } + let IntersectsPoint = new THREE.Vector3(intersects[0].point.x, 0.01, intersects[0].point.z); + if (isAngleSnapped.current && line.current.length > 0 && anglesnappedPoint.current) { + IntersectsPoint = anglesnappedPoint.current; + } + if (visibleIntersect.object instanceof THREE.Mesh) { + const ThroughPoint = (visibleIntersect.object.geometry.parameters.path).getPoints(CONSTANTS.lineConfig.lineIntersectionPoints); + let intersectionPoint = getClosestIntersection(ThroughPoint, IntersectsPoint); + + if (intersectionPoint) { + + const newLines = splitLine(visibleIntersect, intersectionPoint, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, lines, setDeletedLines, floorPlanGroupLine, socket, pointColor, lineColor, intersectsLines[0].object.userData.linePoints[0][3]); + setNewLines([newLines[0], newLines[1]]); + + (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), isSnappedUUID.current!, activeLayer, CONSTANTS.lineConfig.floorName]); + + if (line.current.length >= 2 && line.current[0] && line.current[1]) { + lines.current.push(line.current as Types.Line); + const data = arrayLineToObject(line.current as Types.Line); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setLine(organization, data.layer!, data.line!, data.type!); + + //SOCKET + + const input = { + organization: organization, + layer: data.layer, + line: data.line, + type: data.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input); + + setNewLines([newLines[0], newLines[1], line.current]); + onlyFloorline.current.push(line.current as Types.Line); + onlyFloorlines.current.push(onlyFloorline.current); + onlyFloorline.current = []; + + addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.floorColor, line.current, floorPlanGroupLine); + + removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); + } + return; + } + } + } + } + if (intersects.length > 0 && intersectsLines.length === 0) { + + ////////// Clicked on an empty place or a point ////////// + + let intersectionPoint = intersects[0].point; + + if (isAngleSnapped.current && line.current.length > 0 && anglesnappedPoint.current) { + intersectionPoint = anglesnappedPoint.current; + } + if (isSnapped.current && line.current.length > 0 && snappedPoint.current) { + intersectionPoint = snappedPoint.current; + } + if (ispreSnapped.current && snappedPoint.current) { + intersectionPoint = snappedPoint.current; + } + + if (!isSnapped.current && !ispreSnapped.current) { + addPointToScene(intersectionPoint, CONSTANTS.pointConfig.floorOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, CONSTANTS.lineConfig.floorName); + } else { + ispreSnapped.current = false; + isSnapped.current = false; + } + + (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), isSnappedUUID.current!, activeLayer, CONSTANTS.lineConfig.floorName]); + + if (line.current.length >= 2 && line.current[0] && line.current[1]) { + onlyFloorline.current.push(line.current as Types.Line); + lines.current.push(line.current as Types.Line); + const data = arrayLineToObject(line.current as Types.Line); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setLine(organization, data.layer!, data.line!, data.type!); + + //SOCKET + + const input = { + organization: organization, + layer: data.layer, + line: data.line, + type: data.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input); + + setNewLines([line.current]); + addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.floorColor, line.current, floorPlanGroupLine); + const lastPoint = line.current[line.current.length - 1]; + line.current = [lastPoint]; + } + if (isSnapped.current) { ////////// Add this to stop the drawing mode after snapping ////////// + removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); + onlyFloorlines.current.push(onlyFloorline.current); + onlyFloorline.current = []; + } + } +} + export default drawOnlyFloor; \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/floors/loadFloor.ts b/app/src/modules/builder/geomentries/floors/loadFloor.ts index 30efc62..d4f2fc1 100644 --- a/app/src/modules/builder/geomentries/floors/loadFloor.ts +++ b/app/src/modules/builder/geomentries/floors/loadFloor.ts @@ -1,50 +1,50 @@ -import * as THREE from 'three'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -import addRoofToScene from '../roofs/addRoofToScene'; - -import * as Types from "../../../../types/world/worldTypes"; -import loadOnlyFloors from './loadOnlyFloors'; -import addFloorToScene from './addFloorToScene'; -import getRoomsFromLines from '../lines/getRoomsFromLines'; - -async function loadFloor( - lines: Types.RefLines, - floorGroup: Types.RefGroup, -): Promise { - - if (!floorGroup.current) return; - - floorGroup.current.children = []; - - if (lines.current.length > 2) { - const linesByLayer = lines.current.reduce((acc: { [key: number]: any[] }, pair) => { - const layer = pair[0][2]; - if (!acc[layer]) acc[layer] = []; - acc[layer].push(pair); - return acc; - }, {}); - - for (const layer in linesByLayer) { - // Only Floor Polygons - loadOnlyFloors(floorGroup, linesByLayer, layer); - - const rooms: Types.Rooms = await getRoomsFromLines({ current: linesByLayer[layer] }); - - rooms.forEach(({ coordinates: room, layer }) => { - const userData = room.map(point => point.uuid); - const shape = new THREE.Shape(); - shape.moveTo(room[0].position.x, room[0].position.z); - room.forEach(point => shape.lineTo(point.position.x, point.position.z)); - shape.closePath(); - - // Floor Polygons - addFloorToScene(shape, (layer - 1) * CONSTANTS.wallConfig.height, floorGroup, userData); - - // Roof Polygons - addRoofToScene(shape, (layer - 1) * CONSTANTS.wallConfig.height, userData, floorGroup); - }); - } - } -} - -export default loadFloor; +import * as THREE from 'three'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +import addRoofToScene from '../roofs/addRoofToScene'; + +import * as Types from "../../../../types/world/worldTypes"; +import loadOnlyFloors from './loadOnlyFloors'; +import addFloorToScene from './addFloorToScene'; +import getRoomsFromLines from '../lines/getRoomsFromLines'; + +async function loadFloor( + lines: Types.RefLines, + floorGroup: Types.RefGroup, +): Promise { + + if (!floorGroup.current) return; + + floorGroup.current.children = []; + + if (lines.current.length > 2) { + const linesByLayer = lines.current.reduce((acc: { [key: number]: any[] }, pair) => { + const layer = pair[0][2]; + if (!acc[layer]) acc[layer] = []; + acc[layer].push(pair); + return acc; + }, {}); + + for (const layer in linesByLayer) { + // Only Floor Polygons + loadOnlyFloors(floorGroup, linesByLayer, layer); + + const rooms: Types.Rooms = await getRoomsFromLines({ current: linesByLayer[layer] }); + + rooms.forEach(({ coordinates: room, layer }) => { + const userData = room.map(point => point.uuid); + const shape = new THREE.Shape(); + shape.moveTo(room[0].position.x, room[0].position.z); + room.forEach(point => shape.lineTo(point.position.x, point.position.z)); + shape.closePath(); + + // Floor Polygons + addFloorToScene(shape, (layer - 1) * CONSTANTS.wallConfig.height, floorGroup, userData); + + // Roof Polygons + addRoofToScene(shape, (layer - 1) * CONSTANTS.wallConfig.height, userData, floorGroup); + }); + } + } +} + +export default loadFloor; diff --git a/app/src/modules/builder/geomentries/floors/loadOnlyFloors.ts b/app/src/modules/builder/geomentries/floors/loadOnlyFloors.ts index ca438a2..8f33b57 100644 --- a/app/src/modules/builder/geomentries/floors/loadOnlyFloors.ts +++ b/app/src/modules/builder/geomentries/floors/loadOnlyFloors.ts @@ -1,183 +1,183 @@ -import * as THREE from 'three'; -import * as turf from '@turf/turf'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -import * as Types from "../../../../types/world/worldTypes"; - -function loadOnlyFloors( - floorGroup: Types.RefGroup, - linesByLayer: any, - layer: any, -): void { - - ////////// Creating polygon floor based on the onlyFloorlines.current which does not add roof to it, The lines are still stored in Lines.current as well ////////// - - let floorsInLayer = linesByLayer[layer]; - floorsInLayer = floorsInLayer.filter((line: any) => line[0][3] && line[1][3] === CONSTANTS.lineConfig.floorName); - const floorResult = floorsInLayer.map((pair: [THREE.Vector3, string, number, string][]) => - pair.map((point) => ({ - position: [point[0].x, point[0].z], - uuid: point[1] - })) - ); - const FloorLineFeatures = floorResult.map((line: any) => turf.lineString(line.map((p: any) => p.position))); - - function identifyPolygonsAndConnectedLines(FloorLineFeatures: any) { - const floorpolygons = []; - const connectedLines = []; - const unprocessedLines = [...FloorLineFeatures]; // Copy the features - - while (unprocessedLines.length > 0) { - const currentLine = unprocessedLines.pop(); - const coordinates = currentLine.geometry.coordinates; - - // Check if the line is closed (forms a polygon) - if ( - coordinates[0][0] === coordinates[coordinates.length - 1][0] && - coordinates[0][1] === coordinates[coordinates.length - 1][1] - ) { - floorpolygons.push(turf.polygon([coordinates])); // Add as a polygon - continue; - } - - // Check if the line connects to another line - let connected = false; - for (let i = unprocessedLines.length - 1; i >= 0; i--) { - const otherCoordinates = unprocessedLines[i].geometry.coordinates; - - // Check if lines share a start or end point - if ( - coordinates[0][0] === otherCoordinates[otherCoordinates.length - 1][0] && - coordinates[0][1] === otherCoordinates[otherCoordinates.length - 1][1] - ) { - // Merge lines - const mergedCoordinates = [...otherCoordinates, ...coordinates.slice(1)]; - unprocessedLines[i] = turf.lineString(mergedCoordinates); - connected = true; - break; - } else if ( - coordinates[coordinates.length - 1][0] === otherCoordinates[0][0] && - coordinates[coordinates.length - 1][1] === otherCoordinates[0][1] - ) { - // Merge lines - const mergedCoordinates = [...coordinates, ...otherCoordinates.slice(1)]; - unprocessedLines[i] = turf.lineString(mergedCoordinates); - connected = true; - break; - } - } - - if (!connected) { - connectedLines.push(currentLine); // Add unconnected line as-is - } - } - - return { floorpolygons, connectedLines }; - } - - const { floorpolygons, connectedLines } = identifyPolygonsAndConnectedLines(FloorLineFeatures); - - function convertConnectedLinesToPolygons(connectedLines: any) { - return connectedLines.map((line: any) => { - const coordinates = line.geometry.coordinates; - - // If the line has more than two points, close the polygon - if (coordinates.length > 2) { - const firstPoint = coordinates[0]; - const lastPoint = coordinates[coordinates.length - 1]; - - // Check if already closed; if not, close it - if (firstPoint[0] !== lastPoint[0] || firstPoint[1] !== lastPoint[1]) { - coordinates.push(firstPoint); - } - - // Convert the closed line into a polygon - return turf.polygon([coordinates]); - } - - // If not enough points for a polygon, return the line unchanged - return line; - }); - } - - const convertedConnectedPolygons = convertConnectedLinesToPolygons(connectedLines); - - if (convertedConnectedPolygons.length > 0) { - const validPolygons = convertedConnectedPolygons.filter( - (polygon: any) => polygon.geometry?.type === "Polygon" - ); - - if (validPolygons.length > 0) { - floorpolygons.push(...validPolygons); - } - } - - function convertPolygonsToOriginalFormat(floorpolygons: any, originalLines: [THREE.Vector3, string, number, string][][]) { - return floorpolygons.map((polygon: any) => { - const coordinates = polygon.geometry.coordinates[0]; // Extract the coordinates array (assume it's a single polygon) - - // Map each coordinate back to its original structure - const mappedPoints = coordinates.map((coord: [number, number]) => { - const [x, z] = coord; - - // Find the original point matching this coordinate - const originalPoint = originalLines.flat().find(([point]) => point.x === x && point.z === z); - - if (!originalPoint) { - throw new Error(`Original point for coordinate [${x}, ${z}] not found.`); - } - - return originalPoint; - }); - - // Create pairs of consecutive points - const pairs: typeof originalLines = []; - for (let i = 0; i < mappedPoints.length - 1; i++) { - pairs.push([mappedPoints[i], mappedPoints[i + 1]]); - } - - return pairs; - }); - } - - const convertedFloorPolygons: Types.OnlyFloorLines = convertPolygonsToOriginalFormat(floorpolygons, floorsInLayer); - - convertedFloorPolygons.forEach((floor) => { - const points: THREE.Vector3[] = []; - - floor.forEach((lineSegment) => { - const startPoint = lineSegment[0][0]; - points.push(new THREE.Vector3(startPoint.x, startPoint.y, startPoint.z)); - }); - - const lastLine = floor[floor.length - 1]; - const endPoint = lastLine[1][0]; - points.push(new THREE.Vector3(endPoint.x, endPoint.y, endPoint.z)); - - const shape = new THREE.Shape(); - shape.moveTo(points[0].x, points[0].z); - - points.forEach(point => shape.lineTo(point.x, point.z)); - shape.closePath(); - - const extrudeSettings = { - depth: CONSTANTS.floorConfig.height, - bevelEnabled: false - }; - - const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); - const material = new THREE.MeshStandardMaterial({ color: CONSTANTS.floorConfig.defaultColor, side: THREE.DoubleSide }); - const mesh = new THREE.Mesh(geometry, material); - - mesh.castShadow = true; - mesh.receiveShadow = true; - - mesh.position.y = (floor[0][0][2] - 1) * CONSTANTS.wallConfig.height + 0.03; - mesh.rotateX(Math.PI / 2); - mesh.name = `Only_Floor_Line_${floor[0][0][2]}`; - - mesh.userData = floor; - floorGroup?.current?.add(mesh); - }); -} - -export default loadOnlyFloors; +import * as THREE from 'three'; +import * as turf from '@turf/turf'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +import * as Types from "../../../../types/world/worldTypes"; + +function loadOnlyFloors( + floorGroup: Types.RefGroup, + linesByLayer: any, + layer: any, +): void { + + ////////// Creating polygon floor based on the onlyFloorlines.current which does not add roof to it, The lines are still stored in Lines.current as well ////////// + + let floorsInLayer = linesByLayer[layer]; + floorsInLayer = floorsInLayer.filter((line: any) => line[0][3] && line[1][3] === CONSTANTS.lineConfig.floorName); + const floorResult = floorsInLayer.map((pair: [THREE.Vector3, string, number, string][]) => + pair.map((point) => ({ + position: [point[0].x, point[0].z], + uuid: point[1] + })) + ); + const FloorLineFeatures = floorResult.map((line: any) => turf.lineString(line.map((p: any) => p.position))); + + function identifyPolygonsAndConnectedLines(FloorLineFeatures: any) { + const floorpolygons = []; + const connectedLines = []; + const unprocessedLines = [...FloorLineFeatures]; // Copy the features + + while (unprocessedLines.length > 0) { + const currentLine = unprocessedLines.pop(); + const coordinates = currentLine.geometry.coordinates; + + // Check if the line is closed (forms a polygon) + if ( + coordinates[0][0] === coordinates[coordinates.length - 1][0] && + coordinates[0][1] === coordinates[coordinates.length - 1][1] + ) { + floorpolygons.push(turf.polygon([coordinates])); // Add as a polygon + continue; + } + + // Check if the line connects to another line + let connected = false; + for (let i = unprocessedLines.length - 1; i >= 0; i--) { + const otherCoordinates = unprocessedLines[i].geometry.coordinates; + + // Check if lines share a start or end point + if ( + coordinates[0][0] === otherCoordinates[otherCoordinates.length - 1][0] && + coordinates[0][1] === otherCoordinates[otherCoordinates.length - 1][1] + ) { + // Merge lines + const mergedCoordinates = [...otherCoordinates, ...coordinates.slice(1)]; + unprocessedLines[i] = turf.lineString(mergedCoordinates); + connected = true; + break; + } else if ( + coordinates[coordinates.length - 1][0] === otherCoordinates[0][0] && + coordinates[coordinates.length - 1][1] === otherCoordinates[0][1] + ) { + // Merge lines + const mergedCoordinates = [...coordinates, ...otherCoordinates.slice(1)]; + unprocessedLines[i] = turf.lineString(mergedCoordinates); + connected = true; + break; + } + } + + if (!connected) { + connectedLines.push(currentLine); // Add unconnected line as-is + } + } + + return { floorpolygons, connectedLines }; + } + + const { floorpolygons, connectedLines } = identifyPolygonsAndConnectedLines(FloorLineFeatures); + + function convertConnectedLinesToPolygons(connectedLines: any) { + return connectedLines.map((line: any) => { + const coordinates = line.geometry.coordinates; + + // If the line has more than two points, close the polygon + if (coordinates.length > 2) { + const firstPoint = coordinates[0]; + const lastPoint = coordinates[coordinates.length - 1]; + + // Check if already closed; if not, close it + if (firstPoint[0] !== lastPoint[0] || firstPoint[1] !== lastPoint[1]) { + coordinates.push(firstPoint); + } + + // Convert the closed line into a polygon + return turf.polygon([coordinates]); + } + + // If not enough points for a polygon, return the line unchanged + return line; + }); + } + + const convertedConnectedPolygons = convertConnectedLinesToPolygons(connectedLines); + + if (convertedConnectedPolygons.length > 0) { + const validPolygons = convertedConnectedPolygons.filter( + (polygon: any) => polygon.geometry?.type === "Polygon" + ); + + if (validPolygons.length > 0) { + floorpolygons.push(...validPolygons); + } + } + + function convertPolygonsToOriginalFormat(floorpolygons: any, originalLines: [THREE.Vector3, string, number, string][][]) { + return floorpolygons.map((polygon: any) => { + const coordinates = polygon.geometry.coordinates[0]; // Extract the coordinates array (assume it's a single polygon) + + // Map each coordinate back to its original structure + const mappedPoints = coordinates.map((coord: [number, number]) => { + const [x, z] = coord; + + // Find the original point matching this coordinate + const originalPoint = originalLines.flat().find(([point]) => point.x === x && point.z === z); + + if (!originalPoint) { + throw new Error(`Original point for coordinate [${x}, ${z}] not found.`); + } + + return originalPoint; + }); + + // Create pairs of consecutive points + const pairs: typeof originalLines = []; + for (let i = 0; i < mappedPoints.length - 1; i++) { + pairs.push([mappedPoints[i], mappedPoints[i + 1]]); + } + + return pairs; + }); + } + + const convertedFloorPolygons: Types.OnlyFloorLines = convertPolygonsToOriginalFormat(floorpolygons, floorsInLayer); + + convertedFloorPolygons.forEach((floor) => { + const points: THREE.Vector3[] = []; + + floor.forEach((lineSegment) => { + const startPoint = lineSegment[0][0]; + points.push(new THREE.Vector3(startPoint.x, startPoint.y, startPoint.z)); + }); + + const lastLine = floor[floor.length - 1]; + const endPoint = lastLine[1][0]; + points.push(new THREE.Vector3(endPoint.x, endPoint.y, endPoint.z)); + + const shape = new THREE.Shape(); + shape.moveTo(points[0].x, points[0].z); + + points.forEach(point => shape.lineTo(point.x, point.z)); + shape.closePath(); + + const extrudeSettings = { + depth: CONSTANTS.floorConfig.height, + bevelEnabled: false + }; + + const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); + const material = new THREE.MeshStandardMaterial({ color: CONSTANTS.floorConfig.defaultColor, side: THREE.DoubleSide }); + const mesh = new THREE.Mesh(geometry, material); + + mesh.castShadow = true; + mesh.receiveShadow = true; + + mesh.position.y = (floor[0][0][2] - 1) * CONSTANTS.wallConfig.height + 0.03; + mesh.rotateX(Math.PI / 2); + mesh.name = `Only_Floor_Line_${floor[0][0][2]}`; + + mesh.userData = floor; + floorGroup?.current?.add(mesh); + }); +} + +export default loadOnlyFloors; diff --git a/app/src/modules/builder/geomentries/floors/updateFloorLines.ts b/app/src/modules/builder/geomentries/floors/updateFloorLines.ts index 6aa5ce8..4198a00 100644 --- a/app/src/modules/builder/geomentries/floors/updateFloorLines.ts +++ b/app/src/modules/builder/geomentries/floors/updateFloorLines.ts @@ -1,24 +1,24 @@ -import * as Types from "../../../../types/world/worldTypes"; - -function updateFloorLines( - onlyFloorlines: Types.RefOnlyFloorLines, - DragedPoint: Types.Mesh | { uuid: string, position: Types.Vector3 } -): void { - - ////////// Update onlyFloorlines.current if it contains the dragged point ////////// - - onlyFloorlines.current.forEach((floorline) => { - floorline.forEach((line) => { - line.forEach((point) => { - const [position, uuid] = point; - if (uuid === DragedPoint.uuid) { - position.x = DragedPoint.position.x; - position.y = 0.01; - position.z = DragedPoint.position.z; - } - }); - }); - }); -} - -export default updateFloorLines; +import * as Types from "../../../../types/world/worldTypes"; + +function updateFloorLines( + onlyFloorlines: Types.RefOnlyFloorLines, + DragedPoint: Types.Mesh | { uuid: string, position: Types.Vector3 } +): void { + + ////////// Update onlyFloorlines.current if it contains the dragged point ////////// + + onlyFloorlines.current.forEach((floorline) => { + floorline.forEach((line) => { + line.forEach((point) => { + const [position, uuid] = point; + if (uuid === DragedPoint.uuid) { + position.x = DragedPoint.position.x; + position.y = 0.01; + position.z = DragedPoint.position.z; + } + }); + }); + }); +} + +export default updateFloorLines; diff --git a/app/src/modules/builder/geomentries/layers/deleteLayer.ts b/app/src/modules/builder/geomentries/layers/deleteLayer.ts index c8a4e8a..41afa6e 100644 --- a/app/src/modules/builder/geomentries/layers/deleteLayer.ts +++ b/app/src/modules/builder/geomentries/layers/deleteLayer.ts @@ -1,89 +1,89 @@ -import { toast } from 'react-toastify'; -import RemoveConnectedLines from '../lines/removeConnectedLines'; - -import * as Types from '../../../../types/world/worldTypes'; -import { Socket } from 'socket.io-client'; -// import { deleteLayer } from '../../../../services/factoryBuilder/lines/deleteLayerApi'; - -async function DeleteLayer( - removedLayer: Types.Number, - lines: Types.RefLines, - floorPlanGroupLine: Types.RefGroup, - floorPlanGroupPoint: Types.RefGroup, - onlyFloorlines: Types.RefOnlyFloorLines, - floorGroup: Types.RefGroup, - setDeletedLines: any, - setRemovedLayer: Types.setRemoveLayerSetState, - socket: Socket -): Promise { - - ////////// Remove the Lines from the lines.current based on the removed layer and rearrange the layer number that are higher than the removed layer ////////// - - const removedLines: Types.Lines = lines.current.filter(line => line[0][2] === removedLayer); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // await deleteLayer(organization, removedLayer); - - //SOCKET - - const data = { - organization: organization, - layer: removedLayer, - socketId: socket.id - } - - socket.emit('v1:Line:delete:layer', data); - - ////////// Remove Points and lines from the removed layer ////////// - - removedLines.forEach((line) => { - line.forEach((removedPoint) => { - RemoveConnectedLines(removedPoint[1], floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, lines); - }); - }); - - ////////// Update the remaining lines layer values in the userData and in lines.current ////////// - - let remaining = lines.current.filter(line => line[0][2] !== removedLayer); - let updatedLines: Types.Lines = []; - remaining.forEach(line => { - let newLines: Types.Line = [...line]; - if (newLines[0][2] > removedLayer) { - newLines[0][2] -= 1; - newLines[1][2] -= 1; - } - - const matchingLine = floorPlanGroupLine.current.children.find(l => l.userData.linePoints[0][1] === line[0][1] && l.userData.linePoints[1][1] === line[1][1]); - if (matchingLine) { - const updatedUserData = matchingLine.userData; - updatedUserData.linePoints[0][2] = newLines[0][2]; - updatedUserData.linePoints[1][2] = newLines[1][2]; - } - updatedLines.push(newLines); - }); - - lines.current = updatedLines; - localStorage.setItem("Lines", JSON.stringify(lines.current)); - - ////////// Also remove OnlyFloorLines and update it in localstorage ////////// - - onlyFloorlines.current = onlyFloorlines.current.filter((floor) => { - return floor[0][0][2] !== removedLayer; - }); - const meshToRemove: any = floorGroup.current?.children.find((mesh) => - mesh.name === `Only_Floor_Line_${removedLayer}` - ); - if (meshToRemove) { - (meshToRemove.material).dispose(); - (meshToRemove.geometry).dispose(); - floorGroup.current?.remove(meshToRemove); - } - - toast.success("Layer Removed!"); - setRemovedLayer(null); -} -export default DeleteLayer; +import { toast } from 'react-toastify'; +import RemoveConnectedLines from '../lines/removeConnectedLines'; + +import * as Types from '../../../../types/world/worldTypes'; +import { Socket } from 'socket.io-client'; +// import { deleteLayer } from '../../../../services/factoryBuilder/lines/deleteLayerApi'; + +async function DeleteLayer( + removedLayer: Types.Number, + lines: Types.RefLines, + floorPlanGroupLine: Types.RefGroup, + floorPlanGroupPoint: Types.RefGroup, + onlyFloorlines: Types.RefOnlyFloorLines, + floorGroup: Types.RefGroup, + setDeletedLines: any, + setRemovedLayer: Types.setRemoveLayerSetState, + socket: Socket +): Promise { + + ////////// Remove the Lines from the lines.current based on the removed layer and rearrange the layer number that are higher than the removed layer ////////// + + const removedLines: Types.Lines = lines.current.filter(line => line[0][2] === removedLayer); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // await deleteLayer(organization, removedLayer); + + //SOCKET + + const data = { + organization: organization, + layer: removedLayer, + socketId: socket.id + } + + socket.emit('v1:Line:delete:layer', data); + + ////////// Remove Points and lines from the removed layer ////////// + + removedLines.forEach((line) => { + line.forEach((removedPoint) => { + RemoveConnectedLines(removedPoint[1], floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, lines); + }); + }); + + ////////// Update the remaining lines layer values in the userData and in lines.current ////////// + + let remaining = lines.current.filter(line => line[0][2] !== removedLayer); + let updatedLines: Types.Lines = []; + remaining.forEach(line => { + let newLines: Types.Line = [...line]; + if (newLines[0][2] > removedLayer) { + newLines[0][2] -= 1; + newLines[1][2] -= 1; + } + + const matchingLine = floorPlanGroupLine.current.children.find(l => l.userData.linePoints[0][1] === line[0][1] && l.userData.linePoints[1][1] === line[1][1]); + if (matchingLine) { + const updatedUserData = matchingLine.userData; + updatedUserData.linePoints[0][2] = newLines[0][2]; + updatedUserData.linePoints[1][2] = newLines[1][2]; + } + updatedLines.push(newLines); + }); + + lines.current = updatedLines; + localStorage.setItem("Lines", JSON.stringify(lines.current)); + + ////////// Also remove OnlyFloorLines and update it in localstorage ////////// + + onlyFloorlines.current = onlyFloorlines.current.filter((floor) => { + return floor[0][0][2] !== removedLayer; + }); + const meshToRemove: any = floorGroup.current?.children.find((mesh) => + mesh.name === `Only_Floor_Line_${removedLayer}` + ); + if (meshToRemove) { + (meshToRemove.material).dispose(); + (meshToRemove.geometry).dispose(); + floorGroup.current?.remove(meshToRemove); + } + + toast.success("Layer Removed!"); + setRemovedLayer(null); +} +export default DeleteLayer; diff --git a/app/src/modules/builder/geomentries/layers/layer2DVisibility.ts b/app/src/modules/builder/geomentries/layers/layer2DVisibility.ts index 3164de9..f1828de 100644 --- a/app/src/modules/builder/geomentries/layers/layer2DVisibility.ts +++ b/app/src/modules/builder/geomentries/layers/layer2DVisibility.ts @@ -1,35 +1,35 @@ -import * as Types from "../../../../types/world/worldTypes"; - -function Layer2DVisibility( - activeLayer: Types.Number, - floorPlanGroup: Types.RefGroup, - floorPlanGroupLine: Types.RefGroup, - floorPlanGroupPoint: Types.RefGroup, - currentLayerPoint: Types.RefMeshArray, - dragPointControls: Types.RefDragControl -): void { - - if (floorPlanGroup.current && dragPointControls.current) { - currentLayerPoint.current = []; - floorPlanGroupLine.current.children.forEach((line) => { - const linePoints = line.userData.linePoints; - - const point1 = floorPlanGroupPoint.current.getObjectByProperty('uuid', linePoints[0][1]) as Types.Mesh; - const point2 = floorPlanGroupPoint.current.getObjectByProperty('uuid', linePoints[1][1]) as Types.Mesh; - - if (linePoints[0][2] !== activeLayer && linePoints[1][2] !== activeLayer) { - point1.visible = false; - point2.visible = false; - line.visible = false; - } else { - point1.visible = true; - point2.visible = true; - line.visible = true; - currentLayerPoint.current.push(point1, point2); - } - }); - dragPointControls.current!.objects = currentLayerPoint.current; - } -} - -export default Layer2DVisibility; +import * as Types from "../../../../types/world/worldTypes"; + +function Layer2DVisibility( + activeLayer: Types.Number, + floorPlanGroup: Types.RefGroup, + floorPlanGroupLine: Types.RefGroup, + floorPlanGroupPoint: Types.RefGroup, + currentLayerPoint: Types.RefMeshArray, + dragPointControls: Types.RefDragControl +): void { + + if (floorPlanGroup.current && dragPointControls.current) { + currentLayerPoint.current = []; + floorPlanGroupLine.current.children.forEach((line) => { + const linePoints = line.userData.linePoints; + + const point1 = floorPlanGroupPoint.current.getObjectByProperty('uuid', linePoints[0][1]) as Types.Mesh; + const point2 = floorPlanGroupPoint.current.getObjectByProperty('uuid', linePoints[1][1]) as Types.Mesh; + + if (linePoints[0][2] !== activeLayer && linePoints[1][2] !== activeLayer) { + point1.visible = false; + point2.visible = false; + line.visible = false; + } else { + point1.visible = true; + point2.visible = true; + line.visible = true; + currentLayerPoint.current.push(point1, point2); + } + }); + dragPointControls.current!.objects = currentLayerPoint.current; + } +} + +export default Layer2DVisibility; diff --git a/app/src/modules/builder/geomentries/lines/addLineToScene.ts b/app/src/modules/builder/geomentries/lines/addLineToScene.ts index 79f2a9a..9e30e1d 100644 --- a/app/src/modules/builder/geomentries/lines/addLineToScene.ts +++ b/app/src/modules/builder/geomentries/lines/addLineToScene.ts @@ -1,24 +1,24 @@ -import * as THREE from "three"; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -import * as Types from "../../../../types/world/worldTypes"; - -function addLineToScene( - start: Types.Vector3, - end: Types.Vector3, - colour: Types.Color, - userData: Types.UserData, - floorPlanGroupLine: Types.RefGroup -): void { - - ////////// A function that creates and adds lines based on the start, end, and colour from the params, Also adds the userData in the mesh userData ////////// - - const path = new THREE.CatmullRomCurve3([start, end]); - const geometry = new THREE.TubeGeometry(path, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false); - const material = new THREE.MeshBasicMaterial({ color: colour }); - const mesh = new THREE.Mesh(geometry, material); - floorPlanGroupLine.current.add(mesh); - - mesh.userData.linePoints = userData; -} - -export default addLineToScene; +import * as THREE from "three"; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +import * as Types from "../../../../types/world/worldTypes"; + +function addLineToScene( + start: Types.Vector3, + end: Types.Vector3, + colour: Types.Color, + userData: Types.UserData, + floorPlanGroupLine: Types.RefGroup +): void { + + ////////// A function that creates and adds lines based on the start, end, and colour from the params, Also adds the userData in the mesh userData ////////// + + const path = new THREE.CatmullRomCurve3([start, end]); + const geometry = new THREE.TubeGeometry(path, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false); + const material = new THREE.MeshBasicMaterial({ color: colour }); + const mesh = new THREE.Mesh(geometry, material); + floorPlanGroupLine.current.add(mesh); + + mesh.userData.linePoints = userData; +} + +export default addLineToScene; diff --git a/app/src/modules/builder/geomentries/lines/createAndMoveReferenceLine.ts b/app/src/modules/builder/geomentries/lines/createAndMoveReferenceLine.ts index bcb8e75..e5b6fbe 100644 --- a/app/src/modules/builder/geomentries/lines/createAndMoveReferenceLine.ts +++ b/app/src/modules/builder/geomentries/lines/createAndMoveReferenceLine.ts @@ -1,98 +1,98 @@ -import * as THREE from "three"; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -import * as Types from "../../../../types/world/worldTypes"; - -function createAndMoveReferenceLine( - point: Types.Vector3, - cursorPosition: Types.Vector3, - isSnapped: Types.RefBoolean, - ispreSnapped: Types.RefBoolean, - line: Types.RefLine, - setRefTextUpdate: Types.NumberIncrementState, - floorPlanGroup: Types.RefGroup, - ReferenceLineMesh: Types.RefMesh, - LineCreated: Types.RefBoolean, - Tube: Types.RefTubeGeometry, - anglesnappedPoint: Types.RefVector3, - isAngleSnapped: Types.RefBoolean -): void { - - ////////// Creating new and maintaining the old reference line and also snap the reference line based on its angle ////////// - - const startPoint = point; - - const dx = cursorPosition.x - startPoint.x; - const dz = cursorPosition.z - startPoint.z; - let angle = Math.atan2(dz, dx); - - angle = (angle * 180) / Math.PI; - angle = (angle + 360) % 360; - - const snapAngles = [0, 90, 180, 270, 360]; - const snapThreshold = 2.5; - - const closestSnapAngle = snapAngles.reduce((prev, curr) => - Math.abs(curr - angle) < Math.abs(prev - angle) ? curr : prev - ); - - if (!isSnapped.current && !ispreSnapped.current && line.current.length > 0) { - if (Math.abs(closestSnapAngle - angle) <= snapThreshold) { - const snappedAngleRad = (closestSnapAngle * Math.PI) / 180; - const distance = Math.sqrt(dx * dx + dz * dz); - const snappedX = startPoint.x + distance * Math.cos(snappedAngleRad); - const snappedZ = startPoint.z + distance * Math.sin(snappedAngleRad); - - if ( - cursorPosition.distanceTo( - new THREE.Vector3(snappedX, 0.01, snappedZ) - ) < 2 - ) { - cursorPosition.set(snappedX, 0.01, snappedZ); - isAngleSnapped.current = true; - anglesnappedPoint.current = new THREE.Vector3( - snappedX, - 0.01, - snappedZ - ); - } else { - isAngleSnapped.current = false; - anglesnappedPoint.current = null; - } - } else { - isAngleSnapped.current = false; - anglesnappedPoint.current = null; - } - } else { - isAngleSnapped.current = false; - anglesnappedPoint.current = null; - } - - if (!LineCreated.current) { - setRefTextUpdate((prevUpdate) => prevUpdate - 1); - const path = new THREE.LineCurve3(startPoint, cursorPosition); - Tube.current = new THREE.TubeGeometry(path, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false); - const material = new THREE.MeshBasicMaterial({ color: CONSTANTS.lineConfig.helperColor }); - ReferenceLineMesh.current = new THREE.Mesh(Tube.current, material); - ReferenceLineMesh.current.name = CONSTANTS.lineConfig.referenceName; - ReferenceLineMesh.current.userData = { - linePoints: { startPoint, cursorPosition }, - }; - floorPlanGroup.current?.add(ReferenceLineMesh.current); - LineCreated.current = true; - } else { - if (ReferenceLineMesh.current) { - const path = new THREE.LineCurve3(startPoint, new THREE.Vector3(cursorPosition.x, 0.01, cursorPosition.z)); - Tube.current = new THREE.TubeGeometry(path, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false); - - if (ReferenceLineMesh.current) { - ReferenceLineMesh.current.userData = { - linePoints: { startPoint, cursorPosition }, - }; - ReferenceLineMesh.current.geometry.dispose(); - ReferenceLineMesh.current.geometry = Tube.current; - } - } - } -} - -export default createAndMoveReferenceLine; +import * as THREE from "three"; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +import * as Types from "../../../../types/world/worldTypes"; + +function createAndMoveReferenceLine( + point: Types.Vector3, + cursorPosition: Types.Vector3, + isSnapped: Types.RefBoolean, + ispreSnapped: Types.RefBoolean, + line: Types.RefLine, + setRefTextUpdate: Types.NumberIncrementState, + floorPlanGroup: Types.RefGroup, + ReferenceLineMesh: Types.RefMesh, + LineCreated: Types.RefBoolean, + Tube: Types.RefTubeGeometry, + anglesnappedPoint: Types.RefVector3, + isAngleSnapped: Types.RefBoolean +): void { + + ////////// Creating new and maintaining the old reference line and also snap the reference line based on its angle ////////// + + const startPoint = point; + + const dx = cursorPosition.x - startPoint.x; + const dz = cursorPosition.z - startPoint.z; + let angle = Math.atan2(dz, dx); + + angle = (angle * 180) / Math.PI; + angle = (angle + 360) % 360; + + const snapAngles = [0, 90, 180, 270, 360]; + const snapThreshold = 2.5; + + const closestSnapAngle = snapAngles.reduce((prev, curr) => + Math.abs(curr - angle) < Math.abs(prev - angle) ? curr : prev + ); + + if (!isSnapped.current && !ispreSnapped.current && line.current.length > 0) { + if (Math.abs(closestSnapAngle - angle) <= snapThreshold) { + const snappedAngleRad = (closestSnapAngle * Math.PI) / 180; + const distance = Math.sqrt(dx * dx + dz * dz); + const snappedX = startPoint.x + distance * Math.cos(snappedAngleRad); + const snappedZ = startPoint.z + distance * Math.sin(snappedAngleRad); + + if ( + cursorPosition.distanceTo( + new THREE.Vector3(snappedX, 0.01, snappedZ) + ) < 2 + ) { + cursorPosition.set(snappedX, 0.01, snappedZ); + isAngleSnapped.current = true; + anglesnappedPoint.current = new THREE.Vector3( + snappedX, + 0.01, + snappedZ + ); + } else { + isAngleSnapped.current = false; + anglesnappedPoint.current = null; + } + } else { + isAngleSnapped.current = false; + anglesnappedPoint.current = null; + } + } else { + isAngleSnapped.current = false; + anglesnappedPoint.current = null; + } + + if (!LineCreated.current) { + setRefTextUpdate((prevUpdate) => prevUpdate - 1); + const path = new THREE.LineCurve3(startPoint, cursorPosition); + Tube.current = new THREE.TubeGeometry(path, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false); + const material = new THREE.MeshBasicMaterial({ color: CONSTANTS.lineConfig.helperColor }); + ReferenceLineMesh.current = new THREE.Mesh(Tube.current, material); + ReferenceLineMesh.current.name = CONSTANTS.lineConfig.referenceName; + ReferenceLineMesh.current.userData = { + linePoints: { startPoint, cursorPosition }, + }; + floorPlanGroup.current?.add(ReferenceLineMesh.current); + LineCreated.current = true; + } else { + if (ReferenceLineMesh.current) { + const path = new THREE.LineCurve3(startPoint, new THREE.Vector3(cursorPosition.x, 0.01, cursorPosition.z)); + Tube.current = new THREE.TubeGeometry(path, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false); + + if (ReferenceLineMesh.current) { + ReferenceLineMesh.current.userData = { + linePoints: { startPoint, cursorPosition }, + }; + ReferenceLineMesh.current.geometry.dispose(); + ReferenceLineMesh.current.geometry = Tube.current; + } + } + } +} + +export default createAndMoveReferenceLine; diff --git a/app/src/modules/builder/geomentries/lines/deleteLine.ts b/app/src/modules/builder/geomentries/lines/deleteLine.ts index 66b78a0..14a5e27 100644 --- a/app/src/modules/builder/geomentries/lines/deleteLine.ts +++ b/app/src/modules/builder/geomentries/lines/deleteLine.ts @@ -1,88 +1,88 @@ -import { Socket } from "socket.io-client"; -// import { deleteLineApi } from "../../../../services/factoryBuilder/lines/deleteLineApi"; -import * as Types from "../../../../types/world/worldTypes"; - -import { toast } from 'react-toastify'; - -function deleteLine( - hoveredDeletableLine: Types.RefMesh, - onlyFloorlines: Types.RefOnlyFloorLines, - lines: Types.RefLines, - floorPlanGroupLine: Types.RefGroup, - floorPlanGroupPoint: Types.RefGroup, - setDeletedLines: any, - socket: Socket -): void { - - ////////// Deleting a line and the points if they are not connected to any other line ////////// - - if (!hoveredDeletableLine.current) { - return; - } - - const linePoints = hoveredDeletableLine.current.userData.linePoints; - const connectedpoints = [linePoints[0][1], linePoints[1][1]]; - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // deleteLineApi( - // organization, - // [ - // { "uuid": linePoints[0][1] }, - // { "uuid": linePoints[1][1] } - // ] - // ) - - //SOCKET - - const data = { - organization: organization, - line: [ - { "uuid": linePoints[0][1] }, - { "uuid": linePoints[1][1] } - ], - socketId: socket.id - } - - socket.emit('v1:Line:delete', data); - - - onlyFloorlines.current = onlyFloorlines.current.map(floorline => - floorline.filter(line => line[0][1] !== connectedpoints[0] && line[1][1] !== connectedpoints[1]) - ).filter(floorline => floorline.length > 0); - - lines.current = lines.current.filter(item => item !== linePoints); - (hoveredDeletableLine.current.material).dispose(); - (hoveredDeletableLine.current.geometry).dispose(); - floorPlanGroupLine.current.remove(hoveredDeletableLine.current); - setDeletedLines([linePoints]); - - connectedpoints.forEach((pointUUID) => { - let isConnected = false; - floorPlanGroupLine.current.children.forEach((line) => { - const linePoints = line.userData.linePoints; - const uuid1 = linePoints[0][1]; - const uuid2 = linePoints[1][1]; - if (uuid1 === pointUUID || uuid2 === pointUUID) { - isConnected = true; - } - }); - - if (!isConnected) { - floorPlanGroupPoint.current.children.forEach((point: any) => { - if (point.uuid === pointUUID) { - (point.material).dispose(); - (point.geometry).dispose(); - floorPlanGroupPoint.current.remove(point); - } - }); - } - }); - - toast.success("Line Removed!"); -} - -export default deleteLine; +import { Socket } from "socket.io-client"; +// import { deleteLineApi } from "../../../../services/factoryBuilder/lines/deleteLineApi"; +import * as Types from "../../../../types/world/worldTypes"; + +import { toast } from 'react-toastify'; + +function deleteLine( + hoveredDeletableLine: Types.RefMesh, + onlyFloorlines: Types.RefOnlyFloorLines, + lines: Types.RefLines, + floorPlanGroupLine: Types.RefGroup, + floorPlanGroupPoint: Types.RefGroup, + setDeletedLines: any, + socket: Socket +): void { + + ////////// Deleting a line and the points if they are not connected to any other line ////////// + + if (!hoveredDeletableLine.current) { + return; + } + + const linePoints = hoveredDeletableLine.current.userData.linePoints; + const connectedpoints = [linePoints[0][1], linePoints[1][1]]; + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // deleteLineApi( + // organization, + // [ + // { "uuid": linePoints[0][1] }, + // { "uuid": linePoints[1][1] } + // ] + // ) + + //SOCKET + + const data = { + organization: organization, + line: [ + { "uuid": linePoints[0][1] }, + { "uuid": linePoints[1][1] } + ], + socketId: socket.id + } + + socket.emit('v1:Line:delete', data); + + + onlyFloorlines.current = onlyFloorlines.current.map(floorline => + floorline.filter(line => line[0][1] !== connectedpoints[0] && line[1][1] !== connectedpoints[1]) + ).filter(floorline => floorline.length > 0); + + lines.current = lines.current.filter(item => item !== linePoints); + (hoveredDeletableLine.current.material).dispose(); + (hoveredDeletableLine.current.geometry).dispose(); + floorPlanGroupLine.current.remove(hoveredDeletableLine.current); + setDeletedLines([linePoints]); + + connectedpoints.forEach((pointUUID) => { + let isConnected = false; + floorPlanGroupLine.current.children.forEach((line) => { + const linePoints = line.userData.linePoints; + const uuid1 = linePoints[0][1]; + const uuid2 = linePoints[1][1]; + if (uuid1 === pointUUID || uuid2 === pointUUID) { + isConnected = true; + } + }); + + if (!isConnected) { + floorPlanGroupPoint.current.children.forEach((point: any) => { + if (point.uuid === pointUUID) { + (point.material).dispose(); + (point.geometry).dispose(); + floorPlanGroupPoint.current.remove(point); + } + }); + } + }); + + toast.success("Line Removed!"); +} + +export default deleteLine; diff --git a/app/src/modules/builder/geomentries/lines/distanceText.tsx b/app/src/modules/builder/geomentries/lines/distanceText.tsx index 028d835..0519c84 100644 --- a/app/src/modules/builder/geomentries/lines/distanceText.tsx +++ b/app/src/modules/builder/geomentries/lines/distanceText.tsx @@ -1,90 +1,90 @@ -import { useEffect, useState } from "react" -import { getLines } from "../../../../services/factoryBuilder/lines/getLinesApi"; -import * as THREE from "three"; -import { useActiveLayer, useDeletedLines, useNewLines, useToggleView } from "../../../../store/store"; -import objectLinesToArray from "./lineConvertions/objectLinesToArray"; -import { Html } from "@react-three/drei"; -import * as Types from "../../../../types/world/worldTypes"; - -const DistanceText = () => { - const [lines, setLines] = useState<{ distance: string; position: THREE.Vector3; userData: Types.Line; layer: string }[]>([]); - const { activeLayer } = useActiveLayer(); - const { toggleView } = useToggleView(); - const { newLines, setNewLines } = useNewLines(); - const { deletedLines, setDeletedLines } = useDeletedLines(); - - useEffect(() => { - const email = localStorage.getItem('email') - if (!email) return; - const organization = (email.split("@")[1]).split(".")[0]; - - getLines(organization).then((data) => { - data = objectLinesToArray(data); - - const lines = data.filter((line: Types.Line) => line[0][2] === activeLayer) - .map((line: Types.Line) => { - const point1 = new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z); - const point2 = new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z); - const distance = point1.distanceTo(point2); - const midpoint = new THREE.Vector3().addVectors(point1, point2).divideScalar(2); - return { - distance: distance.toFixed(1), - position: midpoint, - userData: line, - layer: activeLayer, - }; - }); - setLines(lines) - }) - }, [activeLayer]) - - useEffect(() => { - if (newLines.length > 0) { - if (newLines[0][0][2] !== activeLayer) return; - const newLinesData = newLines.map((line: Types.Line) => { - const point1 = new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z); - const point2 = new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z); - const distance = point1.distanceTo(point2); - const midpoint = new THREE.Vector3().addVectors(point1, point2).divideScalar(2); - - return { - distance: distance.toFixed(1), - position: midpoint, - userData: line, - layer: activeLayer, - }; - }); - setLines((prevLines) => [...prevLines, ...newLinesData]); - setNewLines([]); - } - }, [newLines, activeLayer]); - - - useEffect(() => { - if ((deletedLines as Types.Lines).length > 0) { - setLines((prevLines) => - prevLines.filter( - (line) => !deletedLines.some((deletedLine: any) => deletedLine[0][1] === line.userData[0][1] && deletedLine[1][1] === line.userData[1][1]) - ) - ); - setDeletedLines([]); - } - }, [deletedLines]); - - return ( - <> - {toggleView && ( - - {lines.map((text) => ( - -
{text.distance} m
- - ))} -
- )} - - ) - -} - +import { useEffect, useState } from "react" +import { getLines } from "../../../../services/factoryBuilder/lines/getLinesApi"; +import * as THREE from "three"; +import { useActiveLayer, useDeletedLines, useNewLines, useToggleView } from "../../../../store/store"; +import objectLinesToArray from "./lineConvertions/objectLinesToArray"; +import { Html } from "@react-three/drei"; +import * as Types from "../../../../types/world/worldTypes"; + +const DistanceText = () => { + const [lines, setLines] = useState<{ distance: string; position: THREE.Vector3; userData: Types.Line; layer: string }[]>([]); + const { activeLayer } = useActiveLayer(); + const { toggleView } = useToggleView(); + const { newLines, setNewLines } = useNewLines(); + const { deletedLines, setDeletedLines } = useDeletedLines(); + + useEffect(() => { + const email = localStorage.getItem('email') + if (!email) return; + const organization = (email.split("@")[1]).split(".")[0]; + + getLines(organization).then((data) => { + data = objectLinesToArray(data); + + const lines = data.filter((line: Types.Line) => line[0][2] === activeLayer) + .map((line: Types.Line) => { + const point1 = new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z); + const point2 = new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z); + const distance = point1.distanceTo(point2); + const midpoint = new THREE.Vector3().addVectors(point1, point2).divideScalar(2); + return { + distance: distance.toFixed(1), + position: midpoint, + userData: line, + layer: activeLayer, + }; + }); + setLines(lines) + }) + }, [activeLayer]) + + useEffect(() => { + if (newLines.length > 0) { + if (newLines[0][0][2] !== activeLayer) return; + const newLinesData = newLines.map((line: Types.Line) => { + const point1 = new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z); + const point2 = new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z); + const distance = point1.distanceTo(point2); + const midpoint = new THREE.Vector3().addVectors(point1, point2).divideScalar(2); + + return { + distance: distance.toFixed(1), + position: midpoint, + userData: line, + layer: activeLayer, + }; + }); + setLines((prevLines) => [...prevLines, ...newLinesData]); + setNewLines([]); + } + }, [newLines, activeLayer]); + + + useEffect(() => { + if ((deletedLines as Types.Lines).length > 0) { + setLines((prevLines) => + prevLines.filter( + (line) => !deletedLines.some((deletedLine: any) => deletedLine[0][1] === line.userData[0][1] && deletedLine[1][1] === line.userData[1][1]) + ) + ); + setDeletedLines([]); + } + }, [deletedLines]); + + return ( + <> + {toggleView && ( + + {lines.map((text) => ( + +
{text.distance} m
+ + ))} +
+ )} + + ) + +} + export default DistanceText; \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/lines/drawWall.ts b/app/src/modules/builder/geomentries/lines/drawWall.ts index 027e2e9..803f932 100644 --- a/app/src/modules/builder/geomentries/lines/drawWall.ts +++ b/app/src/modules/builder/geomentries/lines/drawWall.ts @@ -1,167 +1,167 @@ -import * as THREE from 'three'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; - -import addPointToScene from '../points/addPointToScene'; -import addLineToScene from './addLineToScene'; -import splitLine from './splitLine'; -import removeReferenceLine from './removeReferenceLine'; -import getClosestIntersection from './getClosestIntersection'; - -import * as Types from "../../../../types/world/worldTypes"; -import arrayLineToObject from './lineConvertions/arrayLineToObject'; -// import { setLine } from '../../../../services/factoryBuilder/lines/setLineApi'; -import { Socket } from 'socket.io-client'; - -async function drawWall( - raycaster: THREE.Raycaster, - plane: Types.RefMesh, - floorPlanGroupPoint: Types.RefGroup, - snappedPoint: Types.RefVector3, - isSnapped: Types.RefBoolean, - isSnappedUUID: Types.RefString, - line: Types.RefLine, - ispreSnapped: Types.RefBoolean, - anglesnappedPoint: Types.RefVector3, - isAngleSnapped: Types.RefBoolean, - lines: Types.RefLines, - floorPlanGroupLine: Types.RefGroup, - floorPlanGroup: Types.RefGroup, - ReferenceLineMesh: Types.RefMesh, - LineCreated: Types.RefBoolean, - currentLayerPoint: Types.RefMeshArray, - dragPointControls: Types.RefDragControl, - setNewLines: any, - setDeletedLines: any, - activeLayer: Types.Number, - socket: Socket -): Promise { - - ////////// Creating lines Based on the positions clicked ////////// - - ////////// Allows the user lines that represents walls and roof, floor if forms a polygon ////////// - - - if (!plane.current) return - let intersects = raycaster.intersectObject(plane.current, true); - - let intersectsLines = raycaster.intersectObjects(floorPlanGroupLine.current.children, true); - let intersectsPoint = raycaster.intersectObjects(floorPlanGroupPoint.current.children, true); - - const VisibleintersectsPoint = intersectsPoint.find(intersect => intersect.object.visible); - const visibleIntersect = intersectsLines.find(intersect => intersect.object.visible && intersect.object.name !== CONSTANTS.lineConfig.referenceName && intersect.object.userData.linePoints[0][3] === CONSTANTS.lineConfig.wallName); - - if ((intersectsPoint.length === 0 || VisibleintersectsPoint === undefined) && intersectsLines.length > 0 && !isSnapped.current && !ispreSnapped.current) { - - ////////// Clicked on a preexisting Line ////////// - - if (visibleIntersect && intersects) { - let IntersectsPoint = new THREE.Vector3(intersects[0].point.x, 0.01, intersects[0].point.z); - - if (isAngleSnapped.current && anglesnappedPoint.current) { - IntersectsPoint = anglesnappedPoint.current; - } - if (visibleIntersect.object instanceof THREE.Mesh) { - const ThroughPoint = (visibleIntersect.object.geometry.parameters.path).getPoints(CONSTANTS.lineConfig.lineIntersectionPoints); - let intersectionPoint = getClosestIntersection(ThroughPoint, IntersectsPoint); - - if (intersectionPoint) { - - const newLines = splitLine(visibleIntersect, intersectionPoint, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, lines, setDeletedLines, floorPlanGroupLine, socket, CONSTANTS.pointConfig.wallOuterColor, CONSTANTS.lineConfig.wallColor, CONSTANTS.lineConfig.wallName); - setNewLines([newLines[0], newLines[1]]); - - (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), isSnappedUUID.current!, activeLayer, CONSTANTS.lineConfig.wallName,]); - - if (line.current.length >= 2 && line.current[0] && line.current[1]) { - const data = arrayLineToObject(line.current as Types.Line); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setLine(organization, data.layer!, data.line!, data.type!); - - //SOCKET - - const input = { - organization: organization, - layer: data.layer, - line: data.line, - type: data.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input); - - setNewLines([newLines[0], newLines[1], line.current]); - lines.current.push(line.current as Types.Line); - addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.wallColor, line.current, floorPlanGroupLine); - let lastPoint = line.current[line.current.length - 1]; - line.current = [lastPoint]; - } - return; - } - } - } - } - - if (intersects && intersects.length > 0) { - - ////////// Clicked on a emply place or a point ////////// - - let intersectionPoint = intersects[0].point; - - if (isAngleSnapped.current && line.current.length > 0 && anglesnappedPoint.current) { - intersectionPoint = anglesnappedPoint.current; - } - if (isSnapped.current && line.current.length > 0 && snappedPoint.current) { - intersectionPoint = snappedPoint.current; - } - if (ispreSnapped.current && snappedPoint.current) { - intersectionPoint = snappedPoint.current; - } - - if (!isSnapped.current && !ispreSnapped.current) { - addPointToScene(intersectionPoint, CONSTANTS.pointConfig.wallOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, CONSTANTS.lineConfig.wallName); - } else { - ispreSnapped.current = false; - isSnapped.current = false; - } - - (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), isSnappedUUID.current!, activeLayer, CONSTANTS.lineConfig.wallName,]); - - if (line.current.length >= 2 && line.current[0] && line.current[1]) { - const data = arrayLineToObject(line.current as Types.Line); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setLine(organization, data.layer!, data.line!, data.type!); - - //SOCKET - - const input = { - organization: organization, - layer: data.layer, - line: data.line, - type: data.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input); - - setNewLines([line.current]) - lines.current.push(line.current as Types.Line); - addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.wallColor, line.current, floorPlanGroupLine); - let lastPoint = line.current[line.current.length - 1]; - line.current = [lastPoint]; - } - if (isSnapped.current) { - removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); - } - } -} - -export default drawWall; +import * as THREE from 'three'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; + +import addPointToScene from '../points/addPointToScene'; +import addLineToScene from './addLineToScene'; +import splitLine from './splitLine'; +import removeReferenceLine from './removeReferenceLine'; +import getClosestIntersection from './getClosestIntersection'; + +import * as Types from "../../../../types/world/worldTypes"; +import arrayLineToObject from './lineConvertions/arrayLineToObject'; +// import { setLine } from '../../../../services/factoryBuilder/lines/setLineApi'; +import { Socket } from 'socket.io-client'; + +async function drawWall( + raycaster: THREE.Raycaster, + plane: Types.RefMesh, + floorPlanGroupPoint: Types.RefGroup, + snappedPoint: Types.RefVector3, + isSnapped: Types.RefBoolean, + isSnappedUUID: Types.RefString, + line: Types.RefLine, + ispreSnapped: Types.RefBoolean, + anglesnappedPoint: Types.RefVector3, + isAngleSnapped: Types.RefBoolean, + lines: Types.RefLines, + floorPlanGroupLine: Types.RefGroup, + floorPlanGroup: Types.RefGroup, + ReferenceLineMesh: Types.RefMesh, + LineCreated: Types.RefBoolean, + currentLayerPoint: Types.RefMeshArray, + dragPointControls: Types.RefDragControl, + setNewLines: any, + setDeletedLines: any, + activeLayer: Types.Number, + socket: Socket +): Promise { + + ////////// Creating lines Based on the positions clicked ////////// + + ////////// Allows the user lines that represents walls and roof, floor if forms a polygon ////////// + + + if (!plane.current) return + let intersects = raycaster.intersectObject(plane.current, true); + + let intersectsLines = raycaster.intersectObjects(floorPlanGroupLine.current.children, true); + let intersectsPoint = raycaster.intersectObjects(floorPlanGroupPoint.current.children, true); + + const VisibleintersectsPoint = intersectsPoint.find(intersect => intersect.object.visible); + const visibleIntersect = intersectsLines.find(intersect => intersect.object.visible && intersect.object.name !== CONSTANTS.lineConfig.referenceName && intersect.object.userData.linePoints[0][3] === CONSTANTS.lineConfig.wallName); + + if ((intersectsPoint.length === 0 || VisibleintersectsPoint === undefined) && intersectsLines.length > 0 && !isSnapped.current && !ispreSnapped.current) { + + ////////// Clicked on a preexisting Line ////////// + + if (visibleIntersect && intersects) { + let IntersectsPoint = new THREE.Vector3(intersects[0].point.x, 0.01, intersects[0].point.z); + + if (isAngleSnapped.current && anglesnappedPoint.current) { + IntersectsPoint = anglesnappedPoint.current; + } + if (visibleIntersect.object instanceof THREE.Mesh) { + const ThroughPoint = (visibleIntersect.object.geometry.parameters.path).getPoints(CONSTANTS.lineConfig.lineIntersectionPoints); + let intersectionPoint = getClosestIntersection(ThroughPoint, IntersectsPoint); + + if (intersectionPoint) { + + const newLines = splitLine(visibleIntersect, intersectionPoint, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, lines, setDeletedLines, floorPlanGroupLine, socket, CONSTANTS.pointConfig.wallOuterColor, CONSTANTS.lineConfig.wallColor, CONSTANTS.lineConfig.wallName); + setNewLines([newLines[0], newLines[1]]); + + (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), isSnappedUUID.current!, activeLayer, CONSTANTS.lineConfig.wallName,]); + + if (line.current.length >= 2 && line.current[0] && line.current[1]) { + const data = arrayLineToObject(line.current as Types.Line); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setLine(organization, data.layer!, data.line!, data.type!); + + //SOCKET + + const input = { + organization: organization, + layer: data.layer, + line: data.line, + type: data.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input); + + setNewLines([newLines[0], newLines[1], line.current]); + lines.current.push(line.current as Types.Line); + addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.wallColor, line.current, floorPlanGroupLine); + let lastPoint = line.current[line.current.length - 1]; + line.current = [lastPoint]; + } + return; + } + } + } + } + + if (intersects && intersects.length > 0) { + + ////////// Clicked on a emply place or a point ////////// + + let intersectionPoint = intersects[0].point; + + if (isAngleSnapped.current && line.current.length > 0 && anglesnappedPoint.current) { + intersectionPoint = anglesnappedPoint.current; + } + if (isSnapped.current && line.current.length > 0 && snappedPoint.current) { + intersectionPoint = snappedPoint.current; + } + if (ispreSnapped.current && snappedPoint.current) { + intersectionPoint = snappedPoint.current; + } + + if (!isSnapped.current && !ispreSnapped.current) { + addPointToScene(intersectionPoint, CONSTANTS.pointConfig.wallOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, CONSTANTS.lineConfig.wallName); + } else { + ispreSnapped.current = false; + isSnapped.current = false; + } + + (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), isSnappedUUID.current!, activeLayer, CONSTANTS.lineConfig.wallName,]); + + if (line.current.length >= 2 && line.current[0] && line.current[1]) { + const data = arrayLineToObject(line.current as Types.Line); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setLine(organization, data.layer!, data.line!, data.type!); + + //SOCKET + + const input = { + organization: organization, + layer: data.layer, + line: data.line, + type: data.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input); + + setNewLines([line.current]) + lines.current.push(line.current as Types.Line); + addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.wallColor, line.current, floorPlanGroupLine); + let lastPoint = line.current[line.current.length - 1]; + line.current = [lastPoint]; + } + if (isSnapped.current) { + removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); + } + } +} + +export default drawWall; diff --git a/app/src/modules/builder/geomentries/lines/getClosestIntersection.ts b/app/src/modules/builder/geomentries/lines/getClosestIntersection.ts index 41d4ecf..587c472 100644 --- a/app/src/modules/builder/geomentries/lines/getClosestIntersection.ts +++ b/app/src/modules/builder/geomentries/lines/getClosestIntersection.ts @@ -1,26 +1,26 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; - -function getClosestIntersection( - intersects: Types.Vector3Array, - point: Types.Vector3 -): Types.Vector3 | null { - - ////////// A function that finds which point is closest from the intersects points that is given, Used in finding which point in a line is closest when clicked on a line during drawing ////////// - - let closestNewPoint: THREE.Vector3 | null = null; - let minDistance = Infinity; - - for (const intersect of intersects) { - const distance = point.distanceTo(intersect); - if (distance < minDistance) { - minDistance = distance; - closestNewPoint = intersect; - } - } - - return closestNewPoint; -} - -export default getClosestIntersection; +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; + +function getClosestIntersection( + intersects: Types.Vector3Array, + point: Types.Vector3 +): Types.Vector3 | null { + + ////////// A function that finds which point is closest from the intersects points that is given, Used in finding which point in a line is closest when clicked on a line during drawing ////////// + + let closestNewPoint: THREE.Vector3 | null = null; + let minDistance = Infinity; + + for (const intersect of intersects) { + const distance = point.distanceTo(intersect); + if (distance < minDistance) { + minDistance = distance; + closestNewPoint = intersect; + } + } + + return closestNewPoint; +} + +export default getClosestIntersection; diff --git a/app/src/modules/builder/geomentries/lines/getRoomsFromLines.ts b/app/src/modules/builder/geomentries/lines/getRoomsFromLines.ts index d521252..08304ea 100644 --- a/app/src/modules/builder/geomentries/lines/getRoomsFromLines.ts +++ b/app/src/modules/builder/geomentries/lines/getRoomsFromLines.ts @@ -1,86 +1,86 @@ -import * as THREE from 'three'; -import * as turf from '@turf/turf'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -import * as Types from "../../../../types/world/worldTypes"; - -async function getRoomsFromLines(lines: Types.RefLines) { - const rooms: Types.Rooms = []; - - if (lines.current.length > 2) { - const linesByLayer = lines.current.reduce((acc: { [key: number]: any[] }, pair) => { - const layer = pair[0][2]; - if (!acc[layer]) acc[layer] = []; - acc[layer].push(pair); - return acc; - }, {}); - - ////////// Use turf.polygonize to create polygons from the line points ////////// - - for (const layer in linesByLayer) { - - let linesInLayer = linesByLayer[layer]; - linesInLayer = linesInLayer.filter(line => line[0][3] && line[1][3] === CONSTANTS.lineConfig.wallName); - const result = linesInLayer.map((pair: [THREE.Vector3, string, number, string][]) => - pair.map((point) => ({ - position: [point[0].x, point[0].z], - uuid: point[1] - })) - ); - const lineFeatures = result.map(line => turf.lineString(line.map(p => p.position))); - const polygons = turf.polygonize(turf.featureCollection(lineFeatures)); - - let union: any[] = []; - - polygons.features.forEach((feature) => { - union.push(feature); - }); - - if (union.length > 1) { - const unionResult = turf.union(turf.featureCollection(union)); - if (unionResult?.geometry.type === "MultiPolygon") { - unionResult?.geometry.coordinates.forEach((poly) => { - const Coordinates = poly[0].map(([x, z]) => { - const matchingPoint = result.flat().find(r => - r.position[0].toFixed(10) === x.toFixed(10) && - r.position[1].toFixed(10) === z.toFixed(10) - ); - return { - position: new THREE.Vector3(x, 0, z), - uuid: matchingPoint ? matchingPoint.uuid : '' - }; - }); - rooms.push({ coordinates: Coordinates.reverse(), layer: parseInt(layer) }); - }); - } else if (unionResult?.geometry.type === "Polygon") { - const Coordinates = unionResult?.geometry.coordinates[0].map(([x, z]) => { - const matchingPoint = result.flat().find(r => - r.position[0].toFixed(10) === x.toFixed(10) && - r.position[1].toFixed(10) === z.toFixed(10) - ); - return { - position: new THREE.Vector3(x, 0, z), - uuid: matchingPoint ? matchingPoint.uuid : '' - }; - }); - rooms.push({ coordinates: Coordinates.reverse(), layer: parseInt(layer) }); - } - } else if (union.length === 1) { - const Coordinates = union[0].geometry.coordinates[0].map(([x, z]: [number, number]) => { - const matchingPoint = result.flat().find(r => - r.position[0].toFixed(10) === x.toFixed(10) && - r.position[1].toFixed(10) === z.toFixed(10) - ); - return { - position: new THREE.Vector3(x, 0, z), - uuid: matchingPoint ? matchingPoint.uuid : '' - }; - }); - rooms.push({ coordinates: Coordinates, layer: parseInt(layer) }); - } - } - } - - return rooms; -} - -export default getRoomsFromLines; +import * as THREE from 'three'; +import * as turf from '@turf/turf'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +import * as Types from "../../../../types/world/worldTypes"; + +async function getRoomsFromLines(lines: Types.RefLines) { + const rooms: Types.Rooms = []; + + if (lines.current.length > 2) { + const linesByLayer = lines.current.reduce((acc: { [key: number]: any[] }, pair) => { + const layer = pair[0][2]; + if (!acc[layer]) acc[layer] = []; + acc[layer].push(pair); + return acc; + }, {}); + + ////////// Use turf.polygonize to create polygons from the line points ////////// + + for (const layer in linesByLayer) { + + let linesInLayer = linesByLayer[layer]; + linesInLayer = linesInLayer.filter(line => line[0][3] && line[1][3] === CONSTANTS.lineConfig.wallName); + const result = linesInLayer.map((pair: [THREE.Vector3, string, number, string][]) => + pair.map((point) => ({ + position: [point[0].x, point[0].z], + uuid: point[1] + })) + ); + const lineFeatures = result.map(line => turf.lineString(line.map(p => p.position))); + const polygons = turf.polygonize(turf.featureCollection(lineFeatures)); + + let union: any[] = []; + + polygons.features.forEach((feature) => { + union.push(feature); + }); + + if (union.length > 1) { + const unionResult = turf.union(turf.featureCollection(union)); + if (unionResult?.geometry.type === "MultiPolygon") { + unionResult?.geometry.coordinates.forEach((poly) => { + const Coordinates = poly[0].map(([x, z]) => { + const matchingPoint = result.flat().find(r => + r.position[0].toFixed(10) === x.toFixed(10) && + r.position[1].toFixed(10) === z.toFixed(10) + ); + return { + position: new THREE.Vector3(x, 0, z), + uuid: matchingPoint ? matchingPoint.uuid : '' + }; + }); + rooms.push({ coordinates: Coordinates.reverse(), layer: parseInt(layer) }); + }); + } else if (unionResult?.geometry.type === "Polygon") { + const Coordinates = unionResult?.geometry.coordinates[0].map(([x, z]) => { + const matchingPoint = result.flat().find(r => + r.position[0].toFixed(10) === x.toFixed(10) && + r.position[1].toFixed(10) === z.toFixed(10) + ); + return { + position: new THREE.Vector3(x, 0, z), + uuid: matchingPoint ? matchingPoint.uuid : '' + }; + }); + rooms.push({ coordinates: Coordinates.reverse(), layer: parseInt(layer) }); + } + } else if (union.length === 1) { + const Coordinates = union[0].geometry.coordinates[0].map(([x, z]: [number, number]) => { + const matchingPoint = result.flat().find(r => + r.position[0].toFixed(10) === x.toFixed(10) && + r.position[1].toFixed(10) === z.toFixed(10) + ); + return { + position: new THREE.Vector3(x, 0, z), + uuid: matchingPoint ? matchingPoint.uuid : '' + }; + }); + rooms.push({ coordinates: Coordinates, layer: parseInt(layer) }); + } + } + } + + return rooms; +} + +export default getRoomsFromLines; diff --git a/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLineToObject.ts b/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLineToObject.ts index d38b18a..dffac05 100644 --- a/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLineToObject.ts +++ b/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLineToObject.ts @@ -1,24 +1,24 @@ -import * as Types from "../../../../../types/world/worldTypes"; - -export default function arrayLineToObject(array: Types.Line) { - if (!Array.isArray(array)) { - return {}; - } - - // Extract common properties from the first point - const commonLayer = array[0][2]; - const commonType = array[0][3]; - - // Map points into a structured format - const line = array.map(([position, uuid]) => ({ - position, - uuid, - })); - - // Create the final structured object - return { - layer: commonLayer, - type: commonType, - line, - }; +import * as Types from "../../../../../types/world/worldTypes"; + +export default function arrayLineToObject(array: Types.Line) { + if (!Array.isArray(array)) { + return {}; + } + + // Extract common properties from the first point + const commonLayer = array[0][2]; + const commonType = array[0][3]; + + // Map points into a structured format + const line = array.map(([position, uuid]) => ({ + position, + uuid, + })); + + // Create the final structured object + return { + layer: commonLayer, + type: commonType, + line, + }; } \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLinesToObject.ts b/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLinesToObject.ts index e41cf4c..041b17c 100644 --- a/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLinesToObject.ts +++ b/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLinesToObject.ts @@ -1,30 +1,30 @@ -import * as Types from "../../../../../types/world/worldTypes"; - -export default function arrayLinesToObject(array: Array) { - if (!Array.isArray(array)) { - return []; - } - - return array.map((lineArray) => { - if (!Array.isArray(lineArray)) { - return null; - } - - // Extract common properties from the first point - const commonLayer = lineArray[0][2]; - const commonType = lineArray[0][3]; - - // Map points into a structured format - const line = lineArray.map(([position, uuid]) => ({ - position, - uuid, - })); - - // Create the final structured object - return { - layer: commonLayer, - type: commonType, - line, - }; - }).filter((item) => item !== null); // Filter out invalid entries -} +import * as Types from "../../../../../types/world/worldTypes"; + +export default function arrayLinesToObject(array: Array) { + if (!Array.isArray(array)) { + return []; + } + + return array.map((lineArray) => { + if (!Array.isArray(lineArray)) { + return null; + } + + // Extract common properties from the first point + const commonLayer = lineArray[0][2]; + const commonType = lineArray[0][3]; + + // Map points into a structured format + const line = lineArray.map(([position, uuid]) => ({ + position, + uuid, + })); + + // Create the final structured object + return { + layer: commonLayer, + type: commonType, + line, + }; + }).filter((item) => item !== null); // Filter out invalid entries +} diff --git a/app/src/modules/builder/geomentries/lines/lineConvertions/objectLineToArray.ts b/app/src/modules/builder/geomentries/lines/lineConvertions/objectLineToArray.ts index a6ee7ea..ac0162c 100644 --- a/app/src/modules/builder/geomentries/lines/lineConvertions/objectLineToArray.ts +++ b/app/src/modules/builder/geomentries/lines/lineConvertions/objectLineToArray.ts @@ -1,13 +1,13 @@ -import * as THREE from 'three'; - -export default function objectLineToArray(structuredObject: any) { - if (!structuredObject || !structuredObject.line) { - return []; - } - - // Destructure common properties - const { layer, type, line } = structuredObject; - - // Map points back to the original array format - return line.map(({ position, uuid }: any) => [new THREE.Vector3(position.x, position.y, position.z), uuid, layer, type]); +import * as THREE from 'three'; + +export default function objectLineToArray(structuredObject: any) { + if (!structuredObject || !structuredObject.line) { + return []; + } + + // Destructure common properties + const { layer, type, line } = structuredObject; + + // Map points back to the original array format + return line.map(({ position, uuid }: any) => [new THREE.Vector3(position.x, position.y, position.z), uuid, layer, type]); } \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/lines/lineConvertions/objectLinesToArray.ts b/app/src/modules/builder/geomentries/lines/lineConvertions/objectLinesToArray.ts index 7f84195..856b935 100644 --- a/app/src/modules/builder/geomentries/lines/lineConvertions/objectLinesToArray.ts +++ b/app/src/modules/builder/geomentries/lines/lineConvertions/objectLinesToArray.ts @@ -1,20 +1,20 @@ -import * as THREE from 'three'; - -export default function objectLinesToArray(structuredObjects: any): any { - if (!Array.isArray(structuredObjects)) { - return []; - } - - return structuredObjects.map((structuredObject) => { - if (!structuredObject || !structuredObject.line) { - return []; - } - - const { layer, type, line } = structuredObject; - - return line.map(({ position, uuid }: any) => { - const vector = new THREE.Vector3(position.x, position.y, position.z); - return [vector, uuid, layer, type]; - }); - }); -} +import * as THREE from 'three'; + +export default function objectLinesToArray(structuredObjects: any): any { + if (!Array.isArray(structuredObjects)) { + return []; + } + + return structuredObjects.map((structuredObject) => { + if (!structuredObject || !structuredObject.line) { + return []; + } + + const { layer, type, line } = structuredObject; + + return line.map(({ position, uuid }: any) => { + const vector = new THREE.Vector3(position.x, position.y, position.z); + return [vector, uuid, layer, type]; + }); + }); +} diff --git a/app/src/modules/builder/geomentries/lines/referenceDistanceText.tsx b/app/src/modules/builder/geomentries/lines/referenceDistanceText.tsx index b1ea8db..cc1ca30 100644 --- a/app/src/modules/builder/geomentries/lines/referenceDistanceText.tsx +++ b/app/src/modules/builder/geomentries/lines/referenceDistanceText.tsx @@ -1,48 +1,48 @@ -import * as THREE from 'three'; -import { Html } from '@react-three/drei'; -import { useState, useEffect } from 'react'; -import { useActiveLayer } from '../../../../store/store'; - -const ReferenceDistanceText = ({ line }: { line: any }) => { - interface TextState { - distance: string; - position: THREE.Vector3; - userData: any; - layer: any; - } - - const [text, setTexts] = useState(null); - const { activeLayer } = useActiveLayer(); - - useEffect(() => { - if (line) { - if (line.parent === null) { - setTexts(null); - return; - } - const distance = line.userData.linePoints.cursorPosition.distanceTo(line.userData.linePoints.startPoint); - const midpoint = new THREE.Vector3().addVectors(line.userData.linePoints.cursorPosition, line.userData.linePoints.startPoint).divideScalar(2); - const newTexts = { - distance: distance.toFixed(1), - position: midpoint, - userData: line, - layer: activeLayer - }; - setTexts(newTexts); - } - }); - - return ( - - - {text !== null && - < Html transform sprite key={text.distance} userData={text.userData} scale={5} position={[text.position.x, 1, text.position.z]} style={{ pointerEvents: 'none' }}> -
{text.distance} m
- - } -
-
- ); -}; - +import * as THREE from 'three'; +import { Html } from '@react-three/drei'; +import { useState, useEffect } from 'react'; +import { useActiveLayer } from '../../../../store/store'; + +const ReferenceDistanceText = ({ line }: { line: any }) => { + interface TextState { + distance: string; + position: THREE.Vector3; + userData: any; + layer: any; + } + + const [text, setTexts] = useState(null); + const { activeLayer } = useActiveLayer(); + + useEffect(() => { + if (line) { + if (line.parent === null) { + setTexts(null); + return; + } + const distance = line.userData.linePoints.cursorPosition.distanceTo(line.userData.linePoints.startPoint); + const midpoint = new THREE.Vector3().addVectors(line.userData.linePoints.cursorPosition, line.userData.linePoints.startPoint).divideScalar(2); + const newTexts = { + distance: distance.toFixed(1), + position: midpoint, + userData: line, + layer: activeLayer + }; + setTexts(newTexts); + } + }); + + return ( + + + {text !== null && + < Html transform sprite key={text.distance} userData={text.userData} scale={5} position={[text.position.x, 1, text.position.z]} style={{ pointerEvents: 'none' }}> +
{text.distance} m
+ + } +
+
+ ); +}; + export default ReferenceDistanceText; \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/lines/removeConnectedLines.ts b/app/src/modules/builder/geomentries/lines/removeConnectedLines.ts index f1399a5..ddf6452 100644 --- a/app/src/modules/builder/geomentries/lines/removeConnectedLines.ts +++ b/app/src/modules/builder/geomentries/lines/removeConnectedLines.ts @@ -1,66 +1,66 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; - -function RemoveConnectedLines( - DeletedPointUUID: Types.String, - floorPlanGroupLine: Types.RefGroup, - floorPlanGroupPoint: Types.RefGroup, - setDeletedLines: any, - lines: Types.RefLines, -): void { - - ////////// Check if any and how many lines are connected to the deleted point ////////// - - const removableLines: THREE.Mesh[] = []; - const connectedpoints: string[] = []; - - const removedLinePoints: [number, string, number][][] = []; // Array to hold linePoints of removed lines - - floorPlanGroupLine.current.children.forEach((line) => { - const linePoints = line.userData.linePoints as [number, string, number][]; - const uuid1 = linePoints[0][1]; - const uuid2 = linePoints[1][1]; - - if (uuid1 === DeletedPointUUID || uuid2 === DeletedPointUUID) { - connectedpoints.push(uuid1 === DeletedPointUUID ? uuid2 : uuid1); - removableLines.push(line as THREE.Mesh); - removedLinePoints.push(linePoints); - } - }); - - if (removableLines.length > 0) { - removableLines.forEach((line) => { - lines.current = lines.current.filter(item => item !== line.userData.linePoints); - (line.material).dispose(); - (line.geometry).dispose(); - floorPlanGroupLine.current.remove(line); - }); - } - setDeletedLines(removedLinePoints) - - ////////// Check and Remove point that are no longer connected to any lines ////////// - - connectedpoints.forEach((pointUUID) => { - let isConnected = false; - floorPlanGroupLine.current.children.forEach((line) => { - const linePoints = line.userData.linePoints as [number, string, number][]; - const uuid1 = linePoints[0][1]; - const uuid2 = linePoints[1][1]; - if (uuid1 === pointUUID || uuid2 === pointUUID) { - isConnected = true; - } - }); - if (!isConnected) { - floorPlanGroupPoint.current.children.forEach((point: any) => { - if (point.uuid === pointUUID) { - (point.material).dispose(); - (point.geometry).dispose(); - floorPlanGroupPoint.current.remove(point); - } - }); - } - }); -} - -export default RemoveConnectedLines; +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; + +function RemoveConnectedLines( + DeletedPointUUID: Types.String, + floorPlanGroupLine: Types.RefGroup, + floorPlanGroupPoint: Types.RefGroup, + setDeletedLines: any, + lines: Types.RefLines, +): void { + + ////////// Check if any and how many lines are connected to the deleted point ////////// + + const removableLines: THREE.Mesh[] = []; + const connectedpoints: string[] = []; + + const removedLinePoints: [number, string, number][][] = []; // Array to hold linePoints of removed lines + + floorPlanGroupLine.current.children.forEach((line) => { + const linePoints = line.userData.linePoints as [number, string, number][]; + const uuid1 = linePoints[0][1]; + const uuid2 = linePoints[1][1]; + + if (uuid1 === DeletedPointUUID || uuid2 === DeletedPointUUID) { + connectedpoints.push(uuid1 === DeletedPointUUID ? uuid2 : uuid1); + removableLines.push(line as THREE.Mesh); + removedLinePoints.push(linePoints); + } + }); + + if (removableLines.length > 0) { + removableLines.forEach((line) => { + lines.current = lines.current.filter(item => item !== line.userData.linePoints); + (line.material).dispose(); + (line.geometry).dispose(); + floorPlanGroupLine.current.remove(line); + }); + } + setDeletedLines(removedLinePoints) + + ////////// Check and Remove point that are no longer connected to any lines ////////// + + connectedpoints.forEach((pointUUID) => { + let isConnected = false; + floorPlanGroupLine.current.children.forEach((line) => { + const linePoints = line.userData.linePoints as [number, string, number][]; + const uuid1 = linePoints[0][1]; + const uuid2 = linePoints[1][1]; + if (uuid1 === pointUUID || uuid2 === pointUUID) { + isConnected = true; + } + }); + if (!isConnected) { + floorPlanGroupPoint.current.children.forEach((point: any) => { + if (point.uuid === pointUUID) { + (point.material).dispose(); + (point.geometry).dispose(); + floorPlanGroupPoint.current.remove(point); + } + }); + } + }); +} + +export default RemoveConnectedLines; diff --git a/app/src/modules/builder/geomentries/lines/removeReferenceLine.ts b/app/src/modules/builder/geomentries/lines/removeReferenceLine.ts index 157805c..787389a 100644 --- a/app/src/modules/builder/geomentries/lines/removeReferenceLine.ts +++ b/app/src/modules/builder/geomentries/lines/removeReferenceLine.ts @@ -1,22 +1,22 @@ -import * as Types from "../../../../types/world/worldTypes"; - -function removeReferenceLine( - floorPlanGroup: Types.RefGroup, - ReferenceLineMesh: Types.RefMesh, - LineCreated: Types.RefBoolean, - line: Types.RefLine -): void { - - ////////// Removes Dangling reference line if the draw mode is ended or any other case ////////// - - line.current = []; - if (ReferenceLineMesh.current) { - (ReferenceLineMesh.current.material).dispose(); - (ReferenceLineMesh.current.geometry).dispose(); - floorPlanGroup.current.remove(ReferenceLineMesh.current); - LineCreated.current = false; - ReferenceLineMesh.current = undefined; - } -} - +import * as Types from "../../../../types/world/worldTypes"; + +function removeReferenceLine( + floorPlanGroup: Types.RefGroup, + ReferenceLineMesh: Types.RefMesh, + LineCreated: Types.RefBoolean, + line: Types.RefLine +): void { + + ////////// Removes Dangling reference line if the draw mode is ended or any other case ////////// + + line.current = []; + if (ReferenceLineMesh.current) { + (ReferenceLineMesh.current.material).dispose(); + (ReferenceLineMesh.current.geometry).dispose(); + floorPlanGroup.current.remove(ReferenceLineMesh.current); + LineCreated.current = false; + ReferenceLineMesh.current = undefined; + } +} + export default removeReferenceLine; \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/lines/splitLine.ts b/app/src/modules/builder/geomentries/lines/splitLine.ts index 557db88..b01a8c7 100644 --- a/app/src/modules/builder/geomentries/lines/splitLine.ts +++ b/app/src/modules/builder/geomentries/lines/splitLine.ts @@ -1,124 +1,124 @@ -import * as THREE from 'three'; - -import addLineToScene from './addLineToScene'; -import addPointToScene from '../points/addPointToScene'; - -import * as Types from "../../../../types/world/worldTypes"; -import arrayLineToObject from '../lines/lineConvertions/arrayLineToObject'; -import { Socket } from 'socket.io-client'; -// import { deleteLineApi } from '../../../../services/factoryBuilder/lines/deleteLineApi'; -// import { setLine } from '../../../../services/factoryBuilder/lines/setLineApi'; - -function splitLine( - visibleIntersect: Types.IntersectionEvent, - intersectionPoint: Types.Vector3, - currentLayerPoint: Types.RefMeshArray, - floorPlanGroupPoint: Types.RefGroup, - dragPointControls: Types.RefDragControl, - isSnappedUUID: Types.RefString, - lines: Types.RefLines, - setDeletedLines: any, - floorPlanGroupLine: { current: THREE.Group }, - socket: Socket, - pointColor: Types.String, - lineColor: Types.String, - lineType: Types.String, -): [Types.Line, Types.Line] { - - ////////// Removing the clicked line and splitting it with the clicked position adding a new point and two new lines ////////// - - - ((visibleIntersect.object as any).material).dispose(); - ((visibleIntersect.object as any).geometry).dispose(); - floorPlanGroupLine.current.remove(visibleIntersect.object); - setDeletedLines([visibleIntersect.object.userData.linePoints]); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // deleteLineApi( - // organization, - // [ - // { "uuid": visibleIntersect.object.userData.linePoints[0][1] }, - // { "uuid": visibleIntersect.object.userData.linePoints[1][1] } - // ] - // ) - - //SOCKET - - - const data = { - organization: organization, - line: [ - { "uuid": visibleIntersect.object.userData.linePoints[0][1] }, - { "uuid": visibleIntersect.object.userData.linePoints[1][1] } - ], - socketId: socket.id - } - - socket.emit('v1:Line:delete', data); - - const point = addPointToScene(intersectionPoint, pointColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, lineType); - - const oldLinePoints = visibleIntersect.object.userData.linePoints; - lines.current = lines.current.filter(item => item !== oldLinePoints); - - const clickedPoint: Types.Point = [ - new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), - point.uuid, - oldLinePoints[0][2], - lineType - ]; - - const start = oldLinePoints[0]; - const end = oldLinePoints[1]; - - const newLine1: Types.Line = [start, clickedPoint]; - const newLine2: Types.Line = [clickedPoint, end]; - - const line1 = arrayLineToObject(newLine1); - const line2 = arrayLineToObject(newLine2); - - //REST - - // setLine(organization, line1.layer!, line1.line!, line1.type!); - - //SOCKET - - const input1 = { - organization: organization, - layer: line1.layer, - line: line1.line, - type: line1.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input1); - - //REST - - // setLine(organization, line2.layer!, line2.line!, line2.type!); - - //SOCKET - - const input2 = { - organization: organization, - layer: line2.layer, - line: line2.line, - type: line2.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input2); - - lines.current.push(newLine1, newLine2); - - addLineToScene(newLine1[0][0], newLine1[1][0], lineColor, newLine1, floorPlanGroupLine); - addLineToScene(newLine2[0][0], newLine2[1][0], lineColor, newLine2, floorPlanGroupLine); - - return [newLine1, newLine2]; -} - -export default splitLine; +import * as THREE from 'three'; + +import addLineToScene from './addLineToScene'; +import addPointToScene from '../points/addPointToScene'; + +import * as Types from "../../../../types/world/worldTypes"; +import arrayLineToObject from '../lines/lineConvertions/arrayLineToObject'; +import { Socket } from 'socket.io-client'; +// import { deleteLineApi } from '../../../../services/factoryBuilder/lines/deleteLineApi'; +// import { setLine } from '../../../../services/factoryBuilder/lines/setLineApi'; + +function splitLine( + visibleIntersect: Types.IntersectionEvent, + intersectionPoint: Types.Vector3, + currentLayerPoint: Types.RefMeshArray, + floorPlanGroupPoint: Types.RefGroup, + dragPointControls: Types.RefDragControl, + isSnappedUUID: Types.RefString, + lines: Types.RefLines, + setDeletedLines: any, + floorPlanGroupLine: { current: THREE.Group }, + socket: Socket, + pointColor: Types.String, + lineColor: Types.String, + lineType: Types.String, +): [Types.Line, Types.Line] { + + ////////// Removing the clicked line and splitting it with the clicked position adding a new point and two new lines ////////// + + + ((visibleIntersect.object as any).material).dispose(); + ((visibleIntersect.object as any).geometry).dispose(); + floorPlanGroupLine.current.remove(visibleIntersect.object); + setDeletedLines([visibleIntersect.object.userData.linePoints]); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // deleteLineApi( + // organization, + // [ + // { "uuid": visibleIntersect.object.userData.linePoints[0][1] }, + // { "uuid": visibleIntersect.object.userData.linePoints[1][1] } + // ] + // ) + + //SOCKET + + + const data = { + organization: organization, + line: [ + { "uuid": visibleIntersect.object.userData.linePoints[0][1] }, + { "uuid": visibleIntersect.object.userData.linePoints[1][1] } + ], + socketId: socket.id + } + + socket.emit('v1:Line:delete', data); + + const point = addPointToScene(intersectionPoint, pointColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, isSnappedUUID, lineType); + + const oldLinePoints = visibleIntersect.object.userData.linePoints; + lines.current = lines.current.filter(item => item !== oldLinePoints); + + const clickedPoint: Types.Point = [ + new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), + point.uuid, + oldLinePoints[0][2], + lineType + ]; + + const start = oldLinePoints[0]; + const end = oldLinePoints[1]; + + const newLine1: Types.Line = [start, clickedPoint]; + const newLine2: Types.Line = [clickedPoint, end]; + + const line1 = arrayLineToObject(newLine1); + const line2 = arrayLineToObject(newLine2); + + //REST + + // setLine(organization, line1.layer!, line1.line!, line1.type!); + + //SOCKET + + const input1 = { + organization: organization, + layer: line1.layer, + line: line1.line, + type: line1.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input1); + + //REST + + // setLine(organization, line2.layer!, line2.line!, line2.type!); + + //SOCKET + + const input2 = { + organization: organization, + layer: line2.layer, + line: line2.line, + type: line2.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input2); + + lines.current.push(newLine1, newLine2); + + addLineToScene(newLine1[0][0], newLine1[1][0], lineColor, newLine1, floorPlanGroupLine); + addLineToScene(newLine2[0][0], newLine2[1][0], lineColor, newLine2, floorPlanGroupLine); + + return [newLine1, newLine2]; +} + +export default splitLine; diff --git a/app/src/modules/builder/geomentries/lines/updateDistanceText.ts b/app/src/modules/builder/geomentries/lines/updateDistanceText.ts index 5909ba9..2f743a9 100644 --- a/app/src/modules/builder/geomentries/lines/updateDistanceText.ts +++ b/app/src/modules/builder/geomentries/lines/updateDistanceText.ts @@ -1,42 +1,42 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; - -function updateDistanceText( - scene: THREE.Scene, - floorPlanGroupLine: Types.RefGroup, - affectedLines: Types.NumberArray -): void { - - ////////// Updating the Distance Texts of the lines that are affected during drag ////////// - - const DistanceGroup = scene.children.find((child) => child.name === "Distance_Text") as THREE.Group; - - affectedLines.forEach((lineIndex) => { - const mesh = floorPlanGroupLine.current.children[lineIndex] as THREE.Mesh; - const linePoints = mesh.userData.linePoints; - - if (linePoints) { - const distance = linePoints[0][0].distanceTo(linePoints[1][0]).toFixed(1); - const position = new THREE.Vector3().addVectors(linePoints[0][0], linePoints[1][0]).divideScalar(2); - - if (!DistanceGroup || !linePoints) { - return - } - - DistanceGroup.children.forEach((text) => { - const textMesh = text as THREE.Mesh; - if (textMesh.userData[0][1] === linePoints[0][1] && textMesh.userData[1][1] === linePoints[1][1]) { - textMesh.position.set(position.x, 1, position.z); - const className = `Distance line-${textMesh.userData[0][1]}_${textMesh.userData[1][1]}_${linePoints[0][2]}`; - const element = document.getElementsByClassName(className)[0] as HTMLElement; - if (element) { - element.innerHTML = `${distance} m`; - } - } - }); - } - }); -} - -export default updateDistanceText; +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; + +function updateDistanceText( + scene: THREE.Scene, + floorPlanGroupLine: Types.RefGroup, + affectedLines: Types.NumberArray +): void { + + ////////// Updating the Distance Texts of the lines that are affected during drag ////////// + + const DistanceGroup = scene.children.find((child) => child.name === "Distance_Text") as THREE.Group; + + affectedLines.forEach((lineIndex) => { + const mesh = floorPlanGroupLine.current.children[lineIndex] as THREE.Mesh; + const linePoints = mesh.userData.linePoints; + + if (linePoints) { + const distance = linePoints[0][0].distanceTo(linePoints[1][0]).toFixed(1); + const position = new THREE.Vector3().addVectors(linePoints[0][0], linePoints[1][0]).divideScalar(2); + + if (!DistanceGroup || !linePoints) { + return + } + + DistanceGroup.children.forEach((text) => { + const textMesh = text as THREE.Mesh; + if (textMesh.userData[0][1] === linePoints[0][1] && textMesh.userData[1][1] === linePoints[1][1]) { + textMesh.position.set(position.x, 1, position.z); + const className = `Distance line-${textMesh.userData[0][1]}_${textMesh.userData[1][1]}_${linePoints[0][2]}`; + const element = document.getElementsByClassName(className)[0] as HTMLElement; + if (element) { + element.innerHTML = `${distance} m`; + } + } + }); + } + }); +} + +export default updateDistanceText; diff --git a/app/src/modules/builder/geomentries/lines/updateLines.ts b/app/src/modules/builder/geomentries/lines/updateLines.ts index 169e452..0c4f22f 100644 --- a/app/src/modules/builder/geomentries/lines/updateLines.ts +++ b/app/src/modules/builder/geomentries/lines/updateLines.ts @@ -1,24 +1,24 @@ -import * as THREE from 'three'; -import * as Types from "../../../../types/world/worldTypes"; -import * as CONSTANTS from '../../../../types/world/worldConstants'; - -function updateLines( - floorPlanGroupLine: Types.RefGroup, - affectedLines: Types.NumberArray -): void { - - ////////// Updating the positions for the affected lines only based on the updated positions ////////// - - affectedLines.forEach((lineIndex) => { - const mesh = floorPlanGroupLine.current.children[lineIndex] as Types.Mesh; - const linePoints = mesh.userData.linePoints as Types.Line; - if (linePoints) { - const newPositions = linePoints.map(([pos]) => pos); - const newPath = new THREE.CatmullRomCurve3(newPositions); - mesh.geometry.dispose(); - mesh.geometry = new THREE.TubeGeometry(newPath, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false); - } - }); -} - +import * as THREE from 'three'; +import * as Types from "../../../../types/world/worldTypes"; +import * as CONSTANTS from '../../../../types/world/worldConstants'; + +function updateLines( + floorPlanGroupLine: Types.RefGroup, + affectedLines: Types.NumberArray +): void { + + ////////// Updating the positions for the affected lines only based on the updated positions ////////// + + affectedLines.forEach((lineIndex) => { + const mesh = floorPlanGroupLine.current.children[lineIndex] as Types.Mesh; + const linePoints = mesh.userData.linePoints as Types.Line; + if (linePoints) { + const newPositions = linePoints.map(([pos]) => pos); + const newPath = new THREE.CatmullRomCurve3(newPositions); + mesh.geometry.dispose(); + mesh.geometry = new THREE.TubeGeometry(newPath, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false); + } + }); +} + export default updateLines; \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/lines/updateLinesPositions.ts b/app/src/modules/builder/geomentries/lines/updateLinesPositions.ts index 4297f4a..6411a09 100644 --- a/app/src/modules/builder/geomentries/lines/updateLinesPositions.ts +++ b/app/src/modules/builder/geomentries/lines/updateLinesPositions.ts @@ -1,32 +1,32 @@ -import * as Types from "../../../../types/world/worldTypes"; - -function updateLinesPositions( - DragedPoint: Types.Mesh | { uuid: string, position: Types.Vector3 }, - lines: Types.RefLines -): Types.NumberArray { - - ////////// Updating the lines position based on the dragged point's position ////////// - - const objectUUID = DragedPoint.uuid; - const affectedLines: Types.NumberArray = []; - - lines.current.forEach((line, index) => { - let lineUpdated = false; - line.forEach((point) => { - const [position, uuid] = point; - if (uuid === objectUUID) { - position.x = DragedPoint.position.x; - position.y = 0.01; - position.z = DragedPoint.position.z; - lineUpdated = true; - } - }); - if (lineUpdated) { - affectedLines.push(index); - } - }); - - return affectedLines; -} - -export default updateLinesPositions; +import * as Types from "../../../../types/world/worldTypes"; + +function updateLinesPositions( + DragedPoint: Types.Mesh | { uuid: string, position: Types.Vector3 }, + lines: Types.RefLines +): Types.NumberArray { + + ////////// Updating the lines position based on the dragged point's position ////////// + + const objectUUID = DragedPoint.uuid; + const affectedLines: Types.NumberArray = []; + + lines.current.forEach((line, index) => { + let lineUpdated = false; + line.forEach((point) => { + const [position, uuid] = point; + if (uuid === objectUUID) { + position.x = DragedPoint.position.x; + position.y = 0.01; + position.z = DragedPoint.position.z; + lineUpdated = true; + } + }); + if (lineUpdated) { + affectedLines.push(index); + } + }); + + return affectedLines; +} + +export default updateLinesPositions; diff --git a/app/src/modules/builder/geomentries/lines/vectorizeLinesCurrent.ts b/app/src/modules/builder/geomentries/lines/vectorizeLinesCurrent.ts index 6bcfd36..a404a07 100644 --- a/app/src/modules/builder/geomentries/lines/vectorizeLinesCurrent.ts +++ b/app/src/modules/builder/geomentries/lines/vectorizeLinesCurrent.ts @@ -1,18 +1,18 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; - -function vectorizeLinesCurrent( - lines: Types.Lines -): Types.Lines { - - ////////// Storing a vector3 array in localstorage makes the prototype functions go puff. This function brings back the prototype functions by creating it again ////////// - - return lines.map((line) => { - const p1: Types.Point = [new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z), line[0][1], line[0][2], line[0][3],]; - const p2: Types.Point = [new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z), line[1][1], line[0][2], line[1][3],]; - return [p1, p2]; - }); -} - -export default vectorizeLinesCurrent; +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; + +function vectorizeLinesCurrent( + lines: Types.Lines +): Types.Lines { + + ////////// Storing a vector3 array in localstorage makes the prototype functions go puff. This function brings back the prototype functions by creating it again ////////// + + return lines.map((line) => { + const p1: Types.Point = [new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z), line[0][1], line[0][2], line[0][3],]; + const p2: Types.Point = [new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z), line[1][1], line[0][2], line[1][3],]; + return [p1, p2]; + }); +} + +export default vectorizeLinesCurrent; diff --git a/app/src/modules/builder/geomentries/pillars/addAndUpdateReferencePillar.ts b/app/src/modules/builder/geomentries/pillars/addAndUpdateReferencePillar.ts index a63ad2b..04cad47 100644 --- a/app/src/modules/builder/geomentries/pillars/addAndUpdateReferencePillar.ts +++ b/app/src/modules/builder/geomentries/pillars/addAndUpdateReferencePillar.ts @@ -1,54 +1,54 @@ -import * as THREE from 'three'; -import updateReferencePolesheight from './updateReferencePolesheight'; - -import * as Types from "../../../../types/world/worldTypes"; - -function addAndUpdateReferencePillar( - raycaster: THREE.Raycaster, - floorGroup: Types.RefGroup, - referencePole: Types.RefMesh -): void { - - ////////// Find Pillars position and scale based on the pointer interaction ////////// - - let Roofs = raycaster.intersectObjects(floorGroup.current.children, true); - const intersected = Roofs.find(intersect => intersect.object.name.includes("Roof") || intersect.object.name.includes("Floor")); - - if (intersected) { - const intersectionPoint = intersected.point; - raycaster.ray.origin.copy(intersectionPoint); - raycaster.ray.direction.set(0, -1, 0); - const belowIntersections = raycaster.intersectObjects(floorGroup.current.children, true); - const validIntersections = belowIntersections.filter(intersect => intersect.object.name.includes("Floor")); - - let distance: Types.Number; - - if (validIntersections.length > 1) { - let valid = validIntersections.find(intersectedBelow => intersected.point.distanceTo(intersectedBelow.point) > 3); - if (valid) { - updateReferencePolesheight(intersectionPoint, valid.distance, referencePole, floorGroup); - } else { - const belowPoint = new THREE.Vector3(intersectionPoint.x, 0, intersectionPoint.z); - distance = intersected.point.distanceTo(belowPoint); - if (distance > 3) { - updateReferencePolesheight(intersectionPoint, distance, referencePole, floorGroup); - } - } - } else { - const belowPoint = new THREE.Vector3(intersectionPoint.x, 0, intersectionPoint.z); - distance = intersected.point.distanceTo(belowPoint); - if (distance > 3) { - updateReferencePolesheight(intersectionPoint, distance, referencePole, floorGroup); - } - } - } else { - if (referencePole.current) { - (referencePole.current.material).dispose(); - (referencePole.current.geometry).dispose(); - floorGroup.current.remove(referencePole.current); - referencePole.current = null; - } - } -} - -export default addAndUpdateReferencePillar; +import * as THREE from 'three'; +import updateReferencePolesheight from './updateReferencePolesheight'; + +import * as Types from "../../../../types/world/worldTypes"; + +function addAndUpdateReferencePillar( + raycaster: THREE.Raycaster, + floorGroup: Types.RefGroup, + referencePole: Types.RefMesh +): void { + + ////////// Find Pillars position and scale based on the pointer interaction ////////// + + let Roofs = raycaster.intersectObjects(floorGroup.current.children, true); + const intersected = Roofs.find(intersect => intersect.object.name.includes("Roof") || intersect.object.name.includes("Floor")); + + if (intersected) { + const intersectionPoint = intersected.point; + raycaster.ray.origin.copy(intersectionPoint); + raycaster.ray.direction.set(0, -1, 0); + const belowIntersections = raycaster.intersectObjects(floorGroup.current.children, true); + const validIntersections = belowIntersections.filter(intersect => intersect.object.name.includes("Floor")); + + let distance: Types.Number; + + if (validIntersections.length > 1) { + let valid = validIntersections.find(intersectedBelow => intersected.point.distanceTo(intersectedBelow.point) > 3); + if (valid) { + updateReferencePolesheight(intersectionPoint, valid.distance, referencePole, floorGroup); + } else { + const belowPoint = new THREE.Vector3(intersectionPoint.x, 0, intersectionPoint.z); + distance = intersected.point.distanceTo(belowPoint); + if (distance > 3) { + updateReferencePolesheight(intersectionPoint, distance, referencePole, floorGroup); + } + } + } else { + const belowPoint = new THREE.Vector3(intersectionPoint.x, 0, intersectionPoint.z); + distance = intersected.point.distanceTo(belowPoint); + if (distance > 3) { + updateReferencePolesheight(intersectionPoint, distance, referencePole, floorGroup); + } + } + } else { + if (referencePole.current) { + (referencePole.current.material).dispose(); + (referencePole.current.geometry).dispose(); + floorGroup.current.remove(referencePole.current); + referencePole.current = null; + } + } +} + +export default addAndUpdateReferencePillar; diff --git a/app/src/modules/builder/geomentries/pillars/addPillar.ts b/app/src/modules/builder/geomentries/pillars/addPillar.ts index 19144fb..e6e4b86 100644 --- a/app/src/modules/builder/geomentries/pillars/addPillar.ts +++ b/app/src/modules/builder/geomentries/pillars/addPillar.ts @@ -1,24 +1,24 @@ -import * as THREE from 'three'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -import * as Types from "../../../../types/world/worldTypes"; - -function addPillar( - referencePole: Types.RefMesh, - floorGroup: Types.RefGroup -): void { - - ////////// Add Pillars to the scene based on the reference. current poles position and scale ////////// - - if (referencePole.current) { - let pole: THREE.Mesh; - const geometry = referencePole.current.userData.geometry.clone(); - const material = new THREE.MeshStandardMaterial({ color: CONSTANTS.columnConfig.defaultColor }); - pole = new THREE.Mesh(geometry, material); - pole.rotateX(Math.PI / 2); - pole.name = "Pole"; - pole.position.set(referencePole.current.userData.position.x, referencePole.current.userData.position.y, referencePole.current.userData.position.z); - floorGroup.current.add(pole); - } -} - +import * as THREE from 'three'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +import * as Types from "../../../../types/world/worldTypes"; + +function addPillar( + referencePole: Types.RefMesh, + floorGroup: Types.RefGroup +): void { + + ////////// Add Pillars to the scene based on the reference. current poles position and scale ////////// + + if (referencePole.current) { + let pole: THREE.Mesh; + const geometry = referencePole.current.userData.geometry.clone(); + const material = new THREE.MeshStandardMaterial({ color: CONSTANTS.columnConfig.defaultColor }); + pole = new THREE.Mesh(geometry, material); + pole.rotateX(Math.PI / 2); + pole.name = "Pole"; + pole.position.set(referencePole.current.userData.position.x, referencePole.current.userData.position.y, referencePole.current.userData.position.z); + floorGroup.current.add(pole); + } +} + export default addPillar; \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/pillars/deletableHoveredPillar.ts b/app/src/modules/builder/geomentries/pillars/deletableHoveredPillar.ts index 0693766..4fb65c0 100644 --- a/app/src/modules/builder/geomentries/pillars/deletableHoveredPillar.ts +++ b/app/src/modules/builder/geomentries/pillars/deletableHoveredPillar.ts @@ -1,34 +1,34 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; - -function DeletableHoveredPillar( - state: Types.ThreeState, - floorGroup: Types.RefGroup, - hoveredDeletablePillar: Types.RefMesh -): void { - - ////////// Altering the color of the hovered Pillar during the Deletion time ////////// - - const intersects = state.raycaster.intersectObjects(floorGroup.current.children, true); - const poleIntersect = intersects.find(intersect => intersect.object.name === "Pole"); - - if (poleIntersect) { - if (poleIntersect.object.name !== "Pole") { - return; - } - if (hoveredDeletablePillar.current) { - (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("black"); - hoveredDeletablePillar.current = undefined; - } - hoveredDeletablePillar.current = poleIntersect.object as THREE.Mesh; // Type assertion - (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("red"); - } else { - if (hoveredDeletablePillar.current) { - (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("black"); - hoveredDeletablePillar.current = undefined; - } - } -} - +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; + +function DeletableHoveredPillar( + state: Types.ThreeState, + floorGroup: Types.RefGroup, + hoveredDeletablePillar: Types.RefMesh +): void { + + ////////// Altering the color of the hovered Pillar during the Deletion time ////////// + + const intersects = state.raycaster.intersectObjects(floorGroup.current.children, true); + const poleIntersect = intersects.find(intersect => intersect.object.name === "Pole"); + + if (poleIntersect) { + if (poleIntersect.object.name !== "Pole") { + return; + } + if (hoveredDeletablePillar.current) { + (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("black"); + hoveredDeletablePillar.current = undefined; + } + hoveredDeletablePillar.current = poleIntersect.object as THREE.Mesh; // Type assertion + (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("red"); + } else { + if (hoveredDeletablePillar.current) { + (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("black"); + hoveredDeletablePillar.current = undefined; + } + } +} + export default DeletableHoveredPillar; \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/pillars/deletePillar.ts b/app/src/modules/builder/geomentries/pillars/deletePillar.ts index 62b4a2c..b735c81 100644 --- a/app/src/modules/builder/geomentries/pillars/deletePillar.ts +++ b/app/src/modules/builder/geomentries/pillars/deletePillar.ts @@ -1,21 +1,21 @@ -import { toast } from 'react-toastify'; - -import * as Types from "../../../../types/world/worldTypes"; - -function DeletePillar( - hoveredDeletablePillar: Types.RefMesh, - floorGroup: Types.RefGroup -): void { - - ////////// Deleting the hovered Pillar from the itemsGroup ////////// - - if (hoveredDeletablePillar.current) { - (hoveredDeletablePillar.current.material).dispose(); - (hoveredDeletablePillar.current.geometry).dispose(); - floorGroup.current.remove(hoveredDeletablePillar.current); - toast.success("Pillar Removed!"); - hoveredDeletablePillar.current = undefined; - } -} - -export default DeletePillar; +import { toast } from 'react-toastify'; + +import * as Types from "../../../../types/world/worldTypes"; + +function DeletePillar( + hoveredDeletablePillar: Types.RefMesh, + floorGroup: Types.RefGroup +): void { + + ////////// Deleting the hovered Pillar from the itemsGroup ////////// + + if (hoveredDeletablePillar.current) { + (hoveredDeletablePillar.current.material).dispose(); + (hoveredDeletablePillar.current.geometry).dispose(); + floorGroup.current.remove(hoveredDeletablePillar.current); + toast.success("Pillar Removed!"); + hoveredDeletablePillar.current = undefined; + } +} + +export default DeletePillar; diff --git a/app/src/modules/builder/geomentries/pillars/updateReferencePolesheight.ts b/app/src/modules/builder/geomentries/pillars/updateReferencePolesheight.ts index 572cc09..f538546 100644 --- a/app/src/modules/builder/geomentries/pillars/updateReferencePolesheight.ts +++ b/app/src/modules/builder/geomentries/pillars/updateReferencePolesheight.ts @@ -1,40 +1,40 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; - -function updateReferencePolesheight( - intersectionPoint: Types.Vector3, - distance: Types.Number, - referencePole: Types.RefMesh, - floorGroup: Types.RefGroup -): void { - - ////////// Add a Reference Pillar and update its position and scale based on the pointer interaction ////////// - - if (referencePole.current) { - (referencePole.current.material).dispose(); - (referencePole.current.geometry).dispose(); - floorGroup.current.remove(referencePole.current); - referencePole.current.geometry.dispose(); - } - - const shape = new THREE.Shape(); - shape.moveTo(0.5, 0); - shape.absarc(0, 0, 0.5, 0, 2 * Math.PI, false); - - const extrudeSettings = { - depth: distance, - bevelEnabled: false, - }; - - const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); - const material = new THREE.MeshBasicMaterial({ color: "green", transparent: true, opacity: 0.5 }); - referencePole.current = new THREE.Mesh(geometry, material); - referencePole.current.rotateX(Math.PI / 2); - referencePole.current.position.set(intersectionPoint.x, intersectionPoint.y - 0.01, intersectionPoint.z); - referencePole.current.userData = { geometry: geometry, distance: distance, position: { x: intersectionPoint.x, y: intersectionPoint.y - 0.01, z: intersectionPoint.z } }; - - floorGroup.current.add(referencePole.current); -} - -export default updateReferencePolesheight; +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; + +function updateReferencePolesheight( + intersectionPoint: Types.Vector3, + distance: Types.Number, + referencePole: Types.RefMesh, + floorGroup: Types.RefGroup +): void { + + ////////// Add a Reference Pillar and update its position and scale based on the pointer interaction ////////// + + if (referencePole.current) { + (referencePole.current.material).dispose(); + (referencePole.current.geometry).dispose(); + floorGroup.current.remove(referencePole.current); + referencePole.current.geometry.dispose(); + } + + const shape = new THREE.Shape(); + shape.moveTo(0.5, 0); + shape.absarc(0, 0, 0.5, 0, 2 * Math.PI, false); + + const extrudeSettings = { + depth: distance, + bevelEnabled: false, + }; + + const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); + const material = new THREE.MeshBasicMaterial({ color: "green", transparent: true, opacity: 0.5 }); + referencePole.current = new THREE.Mesh(geometry, material); + referencePole.current.rotateX(Math.PI / 2); + referencePole.current.position.set(intersectionPoint.x, intersectionPoint.y - 0.01, intersectionPoint.z); + referencePole.current.userData = { geometry: geometry, distance: distance, position: { x: intersectionPoint.x, y: intersectionPoint.y - 0.01, z: intersectionPoint.z } }; + + floorGroup.current.add(referencePole.current); +} + +export default updateReferencePolesheight; diff --git a/app/src/modules/builder/geomentries/points/addPointToScene.ts b/app/src/modules/builder/geomentries/points/addPointToScene.ts index 7a82287..922a6bb 100644 --- a/app/src/modules/builder/geomentries/points/addPointToScene.ts +++ b/app/src/modules/builder/geomentries/points/addPointToScene.ts @@ -1,65 +1,65 @@ -import * as THREE from 'three'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -import * as Types from "../../../../types/world/worldTypes"; - -function addPointToScene( - position: Types.Vector3, - colour: Types.Color, - currentLayerPoint: Types.RefMeshArray, - floorPlanGroupPoint: Types.RefGroup, - dragPointControls: Types.RefDragControl | undefined, - uuid: Types.RefString | undefined, - Type: Types.String -): Types.Mesh { - - ////////// A function that creates and adds a cube (point) with an outline based on the position and colour given as params, It also updates the drag controls objects and sets the box uuid in uuid.current ////////// - - const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale); - const material = new THREE.ShaderMaterial({ - uniforms: { - uColor: { value: new THREE.Color(colour) }, // Blue color for the border - uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square - }, - vertexShader: ` - varying vec2 vUv; - - void main() { - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); - } - `, - fragmentShader: ` - varying vec2 vUv; - uniform vec3 uColor; - uniform vec3 uInnerColor; - - void main() { - // Define the size of the white square as a proportion of the face - float borderThickness = 0.2; // Adjust this value for border thickness - if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && - vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) { - gl_FragColor = vec4(uInnerColor, 1.0); // White inner square - } else { - gl_FragColor = vec4(uColor, 1.0); // Blue border - } - } - `, - }); - const point = new THREE.Mesh(geometry, material); - point.name = "point"; - point.userData = { type: Type, color: colour }; - point.position.set(position.x, 0.01, position.z); - - currentLayerPoint.current.push(point); - floorPlanGroupPoint.current.add(point); - if (uuid) { - uuid.current = point.uuid; - } - if (dragPointControls) { - dragPointControls.current!.objects = currentLayerPoint.current; - } - - return point; -} - -export default addPointToScene; +import * as THREE from 'three'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +import * as Types from "../../../../types/world/worldTypes"; + +function addPointToScene( + position: Types.Vector3, + colour: Types.Color, + currentLayerPoint: Types.RefMeshArray, + floorPlanGroupPoint: Types.RefGroup, + dragPointControls: Types.RefDragControl | undefined, + uuid: Types.RefString | undefined, + Type: Types.String +): Types.Mesh { + + ////////// A function that creates and adds a cube (point) with an outline based on the position and colour given as params, It also updates the drag controls objects and sets the box uuid in uuid.current ////////// + + const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale); + const material = new THREE.ShaderMaterial({ + uniforms: { + uColor: { value: new THREE.Color(colour) }, // Blue color for the border + uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square + }, + vertexShader: ` + varying vec2 vUv; + + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); + } + `, + fragmentShader: ` + varying vec2 vUv; + uniform vec3 uColor; + uniform vec3 uInnerColor; + + void main() { + // Define the size of the white square as a proportion of the face + float borderThickness = 0.2; // Adjust this value for border thickness + if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && + vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) { + gl_FragColor = vec4(uInnerColor, 1.0); // White inner square + } else { + gl_FragColor = vec4(uColor, 1.0); // Blue border + } + } + `, + }); + const point = new THREE.Mesh(geometry, material); + point.name = "point"; + point.userData = { type: Type, color: colour }; + point.position.set(position.x, 0.01, position.z); + + currentLayerPoint.current.push(point); + floorPlanGroupPoint.current.add(point); + if (uuid) { + uuid.current = point.uuid; + } + if (dragPointControls) { + dragPointControls.current!.objects = currentLayerPoint.current; + } + + return point; +} + +export default addPointToScene; diff --git a/app/src/modules/builder/geomentries/points/deletePoint.ts b/app/src/modules/builder/geomentries/points/deletePoint.ts index 9768b21..937e57e 100644 --- a/app/src/modules/builder/geomentries/points/deletePoint.ts +++ b/app/src/modules/builder/geomentries/points/deletePoint.ts @@ -1,57 +1,57 @@ -import * as Types from "../../../../types/world/worldTypes"; - -import { toast } from 'react-toastify'; - -import RemoveConnectedLines from "../lines/removeConnectedLines"; -// import { deletePointApi } from "../../../../services/factoryBuilder/lines/deletePointApi"; -import { Socket } from "socket.io-client"; - -function deletePoint( - hoveredDeletablePoint: Types.RefMesh, - onlyFloorlines: Types.RefOnlyFloorLines, - floorPlanGroupPoint: Types.RefGroup, - floorPlanGroupLine: Types.RefGroup, - lines: Types.RefLines, - setDeletedLines: any, - socket: Socket -): void { - ////////// Deleting a Point and the lines that are connected to it ////////// - - if (!hoveredDeletablePoint.current) { - return; - } - - (hoveredDeletablePoint.current.material).dispose(); - (hoveredDeletablePoint.current.geometry).dispose(); - floorPlanGroupPoint.current.remove(hoveredDeletablePoint.current); - const DeletedPointUUID = hoveredDeletablePoint.current.uuid; - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // deletePointApi(organization, DeletedPointUUID); - - //SOCKET - - const data = { - organization: organization, - uuid: DeletedPointUUID, - socketId: socket.id - } - - socket.emit('v1:Line:delete:point', data); - - ////////// Update onlyFloorlines.current to remove references to the deleted point ////////// - - onlyFloorlines.current = onlyFloorlines.current.map(floorline => - floorline.filter(line => line[0][1] !== DeletedPointUUID && line[1][1] !== DeletedPointUUID) - ).filter(floorline => floorline.length > 0); - - RemoveConnectedLines(DeletedPointUUID, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, lines); - - toast.success("Point Removed!"); -} - -export default deletePoint; +import * as Types from "../../../../types/world/worldTypes"; + +import { toast } from 'react-toastify'; + +import RemoveConnectedLines from "../lines/removeConnectedLines"; +// import { deletePointApi } from "../../../../services/factoryBuilder/lines/deletePointApi"; +import { Socket } from "socket.io-client"; + +function deletePoint( + hoveredDeletablePoint: Types.RefMesh, + onlyFloorlines: Types.RefOnlyFloorLines, + floorPlanGroupPoint: Types.RefGroup, + floorPlanGroupLine: Types.RefGroup, + lines: Types.RefLines, + setDeletedLines: any, + socket: Socket +): void { + ////////// Deleting a Point and the lines that are connected to it ////////// + + if (!hoveredDeletablePoint.current) { + return; + } + + (hoveredDeletablePoint.current.material).dispose(); + (hoveredDeletablePoint.current.geometry).dispose(); + floorPlanGroupPoint.current.remove(hoveredDeletablePoint.current); + const DeletedPointUUID = hoveredDeletablePoint.current.uuid; + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // deletePointApi(organization, DeletedPointUUID); + + //SOCKET + + const data = { + organization: organization, + uuid: DeletedPointUUID, + socketId: socket.id + } + + socket.emit('v1:Line:delete:point', data); + + ////////// Update onlyFloorlines.current to remove references to the deleted point ////////// + + onlyFloorlines.current = onlyFloorlines.current.map(floorline => + floorline.filter(line => line[0][1] !== DeletedPointUUID && line[1][1] !== DeletedPointUUID) + ).filter(floorline => floorline.length > 0); + + RemoveConnectedLines(DeletedPointUUID, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, lines); + + toast.success("Point Removed!"); +} + +export default deletePoint; diff --git a/app/src/modules/builder/geomentries/points/dragPoint.ts b/app/src/modules/builder/geomentries/points/dragPoint.ts index f6aaaa4..6494721 100644 --- a/app/src/modules/builder/geomentries/points/dragPoint.ts +++ b/app/src/modules/builder/geomentries/points/dragPoint.ts @@ -1,44 +1,44 @@ -import * as THREE from "three"; -import * as Types from "../../../../types/world/worldTypes" -import * as CONSTANTS from '../../../../types/world/worldConstants'; - -import updateLinesPositions from "../lines/updateLinesPositions"; -import updateLines from "../lines/updateLines"; -import updateDistanceText from "../lines/updateDistanceText"; -import updateFloorLines from "../floors/updateFloorLines"; - -function DragPoint( - event: Types.IntersectionEvent, - floorPlanGroupPoint: Types.RefGroup, - floorPlanGroupLine: Types.RefGroup, - scene: THREE.Scene, - lines: Types.RefLines, - onlyFloorlines: Types.RefOnlyFloorLines -): void { - - ////////// Calling the line updation of the affected lines and Snapping of the point during the drag ////////// - - const snapThreshold = CONSTANTS.pointConfig.snappingThreshold; - const DragedPoint = event.object as Types.Mesh; - - floorPlanGroupPoint.current.children.forEach((point) => { - let canSnap = - ((DragedPoint.userData.type === CONSTANTS.lineConfig.wallName) && (point.userData.type === CONSTANTS.lineConfig.wallName || point.userData.type === CONSTANTS.lineConfig.floorName)) || - ((DragedPoint.userData.type === CONSTANTS.lineConfig.floorName) && (point.userData.type === CONSTANTS.lineConfig.wallName || point.userData.type === CONSTANTS.lineConfig.floorName)) || - ((DragedPoint.userData.type === CONSTANTS.lineConfig.aisleName) && point.userData.type === CONSTANTS.lineConfig.aisleName); - if (canSnap && point.uuid !== DragedPoint.uuid && point.visible) { - const distance = DragedPoint.position.distanceTo(point.position); - if (distance < snapThreshold) { - DragedPoint.position.copy(point.position); - } - } - }); - - const affectedLines = updateLinesPositions(DragedPoint, lines); - - updateLines(floorPlanGroupLine, affectedLines); - updateDistanceText(scene, floorPlanGroupLine, affectedLines); - updateFloorLines(onlyFloorlines, DragedPoint); -} - +import * as THREE from "three"; +import * as Types from "../../../../types/world/worldTypes" +import * as CONSTANTS from '../../../../types/world/worldConstants'; + +import updateLinesPositions from "../lines/updateLinesPositions"; +import updateLines from "../lines/updateLines"; +import updateDistanceText from "../lines/updateDistanceText"; +import updateFloorLines from "../floors/updateFloorLines"; + +function DragPoint( + event: Types.IntersectionEvent, + floorPlanGroupPoint: Types.RefGroup, + floorPlanGroupLine: Types.RefGroup, + scene: THREE.Scene, + lines: Types.RefLines, + onlyFloorlines: Types.RefOnlyFloorLines +): void { + + ////////// Calling the line updation of the affected lines and Snapping of the point during the drag ////////// + + const snapThreshold = CONSTANTS.pointConfig.snappingThreshold; + const DragedPoint = event.object as Types.Mesh; + + floorPlanGroupPoint.current.children.forEach((point) => { + let canSnap = + ((DragedPoint.userData.type === CONSTANTS.lineConfig.wallName) && (point.userData.type === CONSTANTS.lineConfig.wallName || point.userData.type === CONSTANTS.lineConfig.floorName)) || + ((DragedPoint.userData.type === CONSTANTS.lineConfig.floorName) && (point.userData.type === CONSTANTS.lineConfig.wallName || point.userData.type === CONSTANTS.lineConfig.floorName)) || + ((DragedPoint.userData.type === CONSTANTS.lineConfig.aisleName) && point.userData.type === CONSTANTS.lineConfig.aisleName); + if (canSnap && point.uuid !== DragedPoint.uuid && point.visible) { + const distance = DragedPoint.position.distanceTo(point.position); + if (distance < snapThreshold) { + DragedPoint.position.copy(point.position); + } + } + }); + + const affectedLines = updateLinesPositions(DragedPoint, lines); + + updateLines(floorPlanGroupLine, affectedLines); + updateDistanceText(scene, floorPlanGroupLine, affectedLines); + updateFloorLines(onlyFloorlines, DragedPoint); +} + export default DragPoint; \ No newline at end of file diff --git a/app/src/modules/builder/geomentries/points/removeSoloPoint.ts b/app/src/modules/builder/geomentries/points/removeSoloPoint.ts index de784f1..56d3ee7 100644 --- a/app/src/modules/builder/geomentries/points/removeSoloPoint.ts +++ b/app/src/modules/builder/geomentries/points/removeSoloPoint.ts @@ -1,37 +1,37 @@ -import * as Types from "../../../../types/world/worldTypes"; - -function removeSoloPoint( - line: Types.RefLine, - floorPlanGroupLine: Types.RefGroup, - floorPlanGroupPoint: Types.RefGroup -): void { - - ////////// Remove the point if there is only one point and if it is not connected to any other line and also the reference line ////////// - - if (line.current[0]) { - const pointUUID = line.current[0][1]; - let isConnected = false; - - floorPlanGroupLine.current.children.forEach((line) => { - const linePoints = line.userData.linePoints; - const uuid1 = linePoints[0][1]; - const uuid2 = linePoints[1][1]; - if (uuid1 === pointUUID || uuid2 === pointUUID) { - isConnected = true; - } - }); - - if (!isConnected) { - floorPlanGroupPoint.current.children.forEach((point: any) => { - if (point.uuid === pointUUID) { - (point.material).dispose(); - (point.geometry).dispose(); - floorPlanGroupPoint.current.remove(point); - } - }); - } - line.current = []; - } -} - -export default removeSoloPoint; +import * as Types from "../../../../types/world/worldTypes"; + +function removeSoloPoint( + line: Types.RefLine, + floorPlanGroupLine: Types.RefGroup, + floorPlanGroupPoint: Types.RefGroup +): void { + + ////////// Remove the point if there is only one point and if it is not connected to any other line and also the reference line ////////// + + if (line.current[0]) { + const pointUUID = line.current[0][1]; + let isConnected = false; + + floorPlanGroupLine.current.children.forEach((line) => { + const linePoints = line.userData.linePoints; + const uuid1 = linePoints[0][1]; + const uuid2 = linePoints[1][1]; + if (uuid1 === pointUUID || uuid2 === pointUUID) { + isConnected = true; + } + }); + + if (!isConnected) { + floorPlanGroupPoint.current.children.forEach((point: any) => { + if (point.uuid === pointUUID) { + (point.material).dispose(); + (point.geometry).dispose(); + floorPlanGroupPoint.current.remove(point); + } + }); + } + line.current = []; + } +} + +export default removeSoloPoint; diff --git a/app/src/modules/builder/geomentries/roofs/addRoofToScene.ts b/app/src/modules/builder/geomentries/roofs/addRoofToScene.ts index 1d872de..090dc06 100644 --- a/app/src/modules/builder/geomentries/roofs/addRoofToScene.ts +++ b/app/src/modules/builder/geomentries/roofs/addRoofToScene.ts @@ -1,32 +1,32 @@ -import * as THREE from 'three'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -import * as Types from "../../../../types/world/worldTypes"; - -function addRoofToScene( - shape: Types.Shape, - floor: Types.Number, - userData: Types.UserData, - floorGroup: Types.RefGroup -): void { - - ////////// Creating a Polygon roof from the shape of the Polygon floor ////////// - - const extrudeSettings: THREE.ExtrudeGeometryOptions = { - depth: CONSTANTS.roofConfig.height, - bevelEnabled: false - }; - - const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); - const material = new THREE.MeshStandardMaterial({ color: CONSTANTS.roofConfig.defaultColor, side: THREE.DoubleSide, transparent: true, depthWrite: false }); - const mesh = new THREE.Mesh(geometry, material); - mesh.position.y = CONSTANTS.wallConfig.height + floor; - mesh.castShadow = true; - mesh.receiveShadow = true; - mesh.rotateX(Math.PI / 2); - mesh.userData.uuids = userData; - mesh.name = `Roof_Layer_${(floor / CONSTANTS.wallConfig.height) + 1}`; - - floorGroup.current.add(mesh); -} - -export default addRoofToScene; +import * as THREE from 'three'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +import * as Types from "../../../../types/world/worldTypes"; + +function addRoofToScene( + shape: Types.Shape, + floor: Types.Number, + userData: Types.UserData, + floorGroup: Types.RefGroup +): void { + + ////////// Creating a Polygon roof from the shape of the Polygon floor ////////// + + const extrudeSettings: THREE.ExtrudeGeometryOptions = { + depth: CONSTANTS.roofConfig.height, + bevelEnabled: false + }; + + const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); + const material = new THREE.MeshStandardMaterial({ color: CONSTANTS.roofConfig.defaultColor, side: THREE.DoubleSide, transparent: true, depthWrite: false }); + const mesh = new THREE.Mesh(geometry, material); + mesh.position.y = CONSTANTS.wallConfig.height + floor; + mesh.castShadow = true; + mesh.receiveShadow = true; + mesh.rotateX(Math.PI / 2); + mesh.userData.uuids = userData; + mesh.name = `Roof_Layer_${(floor / CONSTANTS.wallConfig.height) + 1}`; + + floorGroup.current.add(mesh); +} + +export default addRoofToScene; diff --git a/app/src/modules/builder/geomentries/roofs/hideRoof.ts b/app/src/modules/builder/geomentries/roofs/hideRoof.ts index 29d65f1..8eb80f8 100644 --- a/app/src/modules/builder/geomentries/roofs/hideRoof.ts +++ b/app/src/modules/builder/geomentries/roofs/hideRoof.ts @@ -1,47 +1,47 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; - -function hideRoof( - visibility: Types.Boolean, - floorGroup: Types.RefGroup, - camera: THREE.Camera -): void { - - ////////// Toggles the visibility of the roof based on the camera position and the Roof visibility button on UI ////////// - - const v = new THREE.Vector3(); - const u = new THREE.Vector3(); - - if (visibility === true && floorGroup.current) { - for (const child of floorGroup.current.children) { - if (child.name.includes("Roof")) { - const roofChild = child as Types.Mesh; - roofChild.getWorldDirection(v); - camera?.getWorldDirection(u); - if (roofChild.material) { - const materials = Array.isArray(roofChild.material) ? roofChild.material : [roofChild.material]; - materials.forEach(material => { - material.visible = v.dot(u) < 0.25; - }); - } - } - } - } else { - if (floorGroup.current) { - for (const child of floorGroup.current.children) { - if (child.name.includes("Roof")) { - const roofChild = child as Types.Mesh; - if (roofChild.material) { - const materials = Array.isArray(roofChild.material) ? roofChild.material : [roofChild.material]; - materials.forEach(material => { - material.visible = false; - }); - } - } - } - } - } -} - -export default hideRoof; +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; + +function hideRoof( + visibility: Types.Boolean, + floorGroup: Types.RefGroup, + camera: THREE.Camera +): void { + + ////////// Toggles the visibility of the roof based on the camera position and the Roof visibility button on UI ////////// + + const v = new THREE.Vector3(); + const u = new THREE.Vector3(); + + if (visibility === true && floorGroup.current) { + for (const child of floorGroup.current.children) { + if (child.name.includes("Roof")) { + const roofChild = child as Types.Mesh; + roofChild.getWorldDirection(v); + camera?.getWorldDirection(u); + if (roofChild.material) { + const materials = Array.isArray(roofChild.material) ? roofChild.material : [roofChild.material]; + materials.forEach(material => { + material.visible = v.dot(u) < 0.25; + }); + } + } + } + } else { + if (floorGroup.current) { + for (const child of floorGroup.current.children) { + if (child.name.includes("Roof")) { + const roofChild = child as Types.Mesh; + if (roofChild.material) { + const materials = Array.isArray(roofChild.material) ? roofChild.material : [roofChild.material]; + materials.forEach(material => { + material.visible = false; + }); + } + } + } + } + } +} + +export default hideRoof; diff --git a/app/src/modules/builder/geomentries/walls/addWallItems.ts b/app/src/modules/builder/geomentries/walls/addWallItems.ts index 351b375..9c578aa 100644 --- a/app/src/modules/builder/geomentries/walls/addWallItems.ts +++ b/app/src/modules/builder/geomentries/walls/addWallItems.ts @@ -1,108 +1,108 @@ -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; -import { toast } from 'react-toastify'; - -import * as THREE from 'three'; -import * as Types from "../../../../types/world/worldTypes"; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -// import { setWallItem } from '../../../../services/factoryBuilder/assest/wallAsset/setWallItemApi'; -import { Socket } from 'socket.io-client'; - -async function AddWallItems( - selected: Types.String, - raycaster: THREE.Raycaster, - CSGGroup: Types.RefMesh, - AssetConfigurations: Types.AssetConfigurations, - setWallItems: Types.setWallItemSetState, - socket: Socket -): Promise { - - ////////// Load Wall GLtf's and set the positions, rotation, type etc. in state and store in localstorage ////////// - - let intersects = raycaster?.intersectObject(CSGGroup.current!, true); - const wallRaycastIntersection = intersects?.find((child) => child.object.name.includes("WallRaycastReference")); - - if (wallRaycastIntersection) { - const intersectionPoint = wallRaycastIntersection; - const loader = new GLTFLoader(); - loader.load(AssetConfigurations[selected].modelUrl, async (gltf) => { - const model = gltf.scene; - model.userData = { wall: intersectionPoint.object.parent }; - model.children[0].children.forEach((child) => { - if (child.name !== "CSG_REF") { - child.castShadow = true; - child.receiveShadow = true; - } - }); - - const config = AssetConfigurations[selected]; - let positionY = typeof config.positionY === 'function' ? config.positionY(intersectionPoint) : config.positionY; - if (positionY === 0) { - positionY = Math.floor(intersectionPoint.point.y / CONSTANTS.wallConfig.height) * CONSTANTS.wallConfig.height; - } - - const newWallItem = { - type: config.type, - model: model, - modelname: selected, - scale: config.scale, - csgscale: config.csgscale, - csgposition: config.csgposition, - position: [intersectionPoint.point.x, positionY, intersectionPoint.point.z] as [number, number, number], - quaternion: intersectionPoint.object.quaternion.clone() as Types.QuaternionType - }; - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // await setWallItem( - // organization, - // model.uuid, - // newWallItem.modelname, - // newWallItem.type!, - // newWallItem.csgposition!, - // newWallItem.csgscale!, - // newWallItem.position, - // newWallItem.quaternion, - // newWallItem.scale!, - // ) - - //SOCKET - - const data = { - organization: organization, - modeluuid: model.uuid, - modelname: newWallItem.modelname, - type: newWallItem.type!, - csgposition: newWallItem.csgposition!, - csgscale: newWallItem.csgscale!, - position: newWallItem.position, - quaternion: newWallItem.quaternion, - scale: newWallItem.scale!, - socketId: socket.id - } - - socket.emit('v1:wallItems:set', data); - - setWallItems((prevItems) => { - const updatedItems = [...prevItems, newWallItem]; - - const WallItemsForStorage = updatedItems.map(item => { - const { model, ...rest } = item; - return { - ...rest, - modeluuid: model?.uuid, - }; - }); - - localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); - toast.success("Model Added!"); - - return updatedItems; - }); - }); - } -} - -export default AddWallItems; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import { toast } from 'react-toastify'; + +import * as THREE from 'three'; +import * as Types from "../../../../types/world/worldTypes"; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +// import { setWallItem } from '../../../../services/factoryBuilder/assest/wallAsset/setWallItemApi'; +import { Socket } from 'socket.io-client'; + +async function AddWallItems( + selected: Types.String, + raycaster: THREE.Raycaster, + CSGGroup: Types.RefMesh, + AssetConfigurations: Types.AssetConfigurations, + setWallItems: Types.setWallItemSetState, + socket: Socket +): Promise { + + ////////// Load Wall GLtf's and set the positions, rotation, type etc. in state and store in localstorage ////////// + + let intersects = raycaster?.intersectObject(CSGGroup.current!, true); + const wallRaycastIntersection = intersects?.find((child) => child.object.name.includes("WallRaycastReference")); + + if (wallRaycastIntersection) { + const intersectionPoint = wallRaycastIntersection; + const loader = new GLTFLoader(); + loader.load(AssetConfigurations[selected].modelUrl, async (gltf) => { + const model = gltf.scene; + model.userData = { wall: intersectionPoint.object.parent }; + model.children[0].children.forEach((child) => { + if (child.name !== "CSG_REF") { + child.castShadow = true; + child.receiveShadow = true; + } + }); + + const config = AssetConfigurations[selected]; + let positionY = typeof config.positionY === 'function' ? config.positionY(intersectionPoint) : config.positionY; + if (positionY === 0) { + positionY = Math.floor(intersectionPoint.point.y / CONSTANTS.wallConfig.height) * CONSTANTS.wallConfig.height; + } + + const newWallItem = { + type: config.type, + model: model, + modelname: selected, + scale: config.scale, + csgscale: config.csgscale, + csgposition: config.csgposition, + position: [intersectionPoint.point.x, positionY, intersectionPoint.point.z] as [number, number, number], + quaternion: intersectionPoint.object.quaternion.clone() as Types.QuaternionType + }; + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // await setWallItem( + // organization, + // model.uuid, + // newWallItem.modelname, + // newWallItem.type!, + // newWallItem.csgposition!, + // newWallItem.csgscale!, + // newWallItem.position, + // newWallItem.quaternion, + // newWallItem.scale!, + // ) + + //SOCKET + + const data = { + organization: organization, + modeluuid: model.uuid, + modelname: newWallItem.modelname, + type: newWallItem.type!, + csgposition: newWallItem.csgposition!, + csgscale: newWallItem.csgscale!, + position: newWallItem.position, + quaternion: newWallItem.quaternion, + scale: newWallItem.scale!, + socketId: socket.id + } + + socket.emit('v1:wallItems:set', data); + + setWallItems((prevItems) => { + const updatedItems = [...prevItems, newWallItem]; + + const WallItemsForStorage = updatedItems.map(item => { + const { model, ...rest } = item; + return { + ...rest, + modeluuid: model?.uuid, + }; + }); + + localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); + toast.success("Model Added!"); + + return updatedItems; + }); + }); + } +} + +export default AddWallItems; diff --git a/app/src/modules/builder/geomentries/walls/deleteWallItems.ts b/app/src/modules/builder/geomentries/walls/deleteWallItems.ts index 2f3373b..abbf0c8 100644 --- a/app/src/modules/builder/geomentries/walls/deleteWallItems.ts +++ b/app/src/modules/builder/geomentries/walls/deleteWallItems.ts @@ -1,59 +1,59 @@ -import { toast } from 'react-toastify'; - -import * as Types from "../../../../types/world/worldTypes"; -// import { deleteWallItem } from '../../../../services/factoryBuilder/assest/wallAsset/deleteWallItemApi'; -import { Socket } from 'socket.io-client'; - -function DeleteWallItems( - hoveredDeletableWallItem: Types.RefMesh, - setWallItems: Types.setWallItemSetState, - wallItems: Types.wallItems, - socket: Socket -): void { - - ////////// Deleting the hovered Wall GLTF from thewallItems and also update it in the localstorage ////////// - - if (hoveredDeletableWallItem.current && hoveredDeletableWallItem.current.parent) { - setWallItems([]); - let WallItemsRef = wallItems; - const removedItem = WallItemsRef.find((item) => item.model?.uuid === hoveredDeletableWallItem.current?.parent?.uuid); - const Items = WallItemsRef.filter((item) => item.model?.uuid !== hoveredDeletableWallItem.current?.parent?.uuid); - - setTimeout(async () => { - WallItemsRef = Items; - setWallItems(WallItemsRef); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // await deleteWallItem(organization, removedItem?.model?.uuid!, removedItem?.modelname!) - - //SOCKET - - const data = { - organization: organization, - modeluuid: removedItem?.model?.uuid!, - modelname: removedItem?.modelname!, - socketId: socket.id - } - - socket.emit('v1:wallItems:delete', data); - - const WallItemsForStorage = WallItemsRef.map(item => { - const { model, ...rest } = item; - return { - ...rest, - modeluuid: model?.uuid, - }; - }); - - localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); - toast.success("Model Removed!"); - hoveredDeletableWallItem.current = null; - }, 50); - } -} - -export default DeleteWallItems; +import { toast } from 'react-toastify'; + +import * as Types from "../../../../types/world/worldTypes"; +// import { deleteWallItem } from '../../../../services/factoryBuilder/assest/wallAsset/deleteWallItemApi'; +import { Socket } from 'socket.io-client'; + +function DeleteWallItems( + hoveredDeletableWallItem: Types.RefMesh, + setWallItems: Types.setWallItemSetState, + wallItems: Types.wallItems, + socket: Socket +): void { + + ////////// Deleting the hovered Wall GLTF from thewallItems and also update it in the localstorage ////////// + + if (hoveredDeletableWallItem.current && hoveredDeletableWallItem.current.parent) { + setWallItems([]); + let WallItemsRef = wallItems; + const removedItem = WallItemsRef.find((item) => item.model?.uuid === hoveredDeletableWallItem.current?.parent?.uuid); + const Items = WallItemsRef.filter((item) => item.model?.uuid !== hoveredDeletableWallItem.current?.parent?.uuid); + + setTimeout(async () => { + WallItemsRef = Items; + setWallItems(WallItemsRef); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // await deleteWallItem(organization, removedItem?.model?.uuid!, removedItem?.modelname!) + + //SOCKET + + const data = { + organization: organization, + modeluuid: removedItem?.model?.uuid!, + modelname: removedItem?.modelname!, + socketId: socket.id + } + + socket.emit('v1:wallItems:delete', data); + + const WallItemsForStorage = WallItemsRef.map(item => { + const { model, ...rest } = item; + return { + ...rest, + modeluuid: model?.uuid, + }; + }); + + localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); + toast.success("Model Removed!"); + hoveredDeletableWallItem.current = null; + }, 50); + } +} + +export default DeleteWallItems; diff --git a/app/src/modules/builder/geomentries/walls/hideWalls.ts b/app/src/modules/builder/geomentries/walls/hideWalls.ts index bba582e..f8bf52a 100644 --- a/app/src/modules/builder/geomentries/walls/hideWalls.ts +++ b/app/src/modules/builder/geomentries/walls/hideWalls.ts @@ -1,45 +1,45 @@ -import * as THREE from 'three'; - -import * as Types from "../../../../types/world/worldTypes"; - -function hideWalls( - visibility: Types.Boolean, - scene: THREE.Scene, - camera: THREE.Camera -): void { - - ////////// Altering the visibility of the Walls when the world direction of the wall is facing the camera ////////// - - const v = new THREE.Vector3(); - const u = new THREE.Vector3(); - - if (visibility === true) { - for (const children of scene.children) { - if (children.name === "Walls" && children.children[0]?.children.length > 0) { - children.children[0].children.forEach((child: any) => { - if (child.children[0]?.userData.WallType === "RoomWall") { - child.children[0].getWorldDirection(v); - camera.getWorldDirection(u); - if (child.children[0].material) { - child.children[0].material.visible = (2 * v.dot(u)) >= -0.5; - } - } - }); - } - } - } else { - for (const children of scene.children) { - if (children.name === "Walls" && children.children[0]?.children.length > 0) { - children.children[0].children.forEach((child: any) => { - if (child.children[0]?.userData.WallType === "RoomWall") { - if (child.children[0].material) { - child.children[0].material.visible = true; - } - } - }); - } - } - } -} - -export default hideWalls; +import * as THREE from 'three'; + +import * as Types from "../../../../types/world/worldTypes"; + +function hideWalls( + visibility: Types.Boolean, + scene: THREE.Scene, + camera: THREE.Camera +): void { + + ////////// Altering the visibility of the Walls when the world direction of the wall is facing the camera ////////// + + const v = new THREE.Vector3(); + const u = new THREE.Vector3(); + + if (visibility === true) { + for (const children of scene.children) { + if (children.name === "Walls" && children.children[0]?.children.length > 0) { + children.children[0].children.forEach((child: any) => { + if (child.children[0]?.userData.WallType === "RoomWall") { + child.children[0].getWorldDirection(v); + camera.getWorldDirection(u); + if (child.children[0].material) { + child.children[0].material.visible = (2 * v.dot(u)) >= -0.5; + } + } + }); + } + } + } else { + for (const children of scene.children) { + if (children.name === "Walls" && children.children[0]?.children.length > 0) { + children.children[0].children.forEach((child: any) => { + if (child.children[0]?.userData.WallType === "RoomWall") { + if (child.children[0].material) { + child.children[0].material.visible = true; + } + } + }); + } + } + } +} + +export default hideWalls; diff --git a/app/src/modules/builder/geomentries/walls/loadWalls.ts b/app/src/modules/builder/geomentries/walls/loadWalls.ts index 0947a6b..d594e5a 100644 --- a/app/src/modules/builder/geomentries/walls/loadWalls.ts +++ b/app/src/modules/builder/geomentries/walls/loadWalls.ts @@ -1,129 +1,129 @@ -import * as THREE from 'three'; -import * as turf from '@turf/turf'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; - -import * as Types from "../../../../types/world/worldTypes"; -import getRoomsFromLines from '../lines/getRoomsFromLines'; - -async function loadWalls( - lines: Types.RefLines, - setWalls: any, -): Promise { - ////////// Removes the old walls if any, Checks if there is any overlapping in lines if any updates it , starts function that creates floor and roof ////////// - - const Walls: Types.Walls = []; - const Rooms: Types.Rooms = []; - - localStorage.setItem("Lines", JSON.stringify(lines.current)); - - if (lines.current.length > 1) { - - ////////// Add Walls that are forming a room ////////// - - const wallSet = new Set(); - - const rooms: Types.Rooms = await getRoomsFromLines(lines); - Rooms.push(...rooms); - - Rooms.forEach(({ coordinates: room, layer }) => { - for (let i = 0; i < room.length - 1; i++) { - const uuid1 = room[i].uuid; - const uuid2 = room[(i + 1) % room.length].uuid; - const wallId = `${uuid1}_${uuid2}`; - - if (!wallSet.has(wallId)) { - const p1 = room[i].position; - const p2 = room[(i + 1) % room.length].position; - - const shape = new THREE.Shape(); - shape.moveTo(0, 0); - shape.lineTo(0, CONSTANTS.wallConfig.height); - shape.lineTo(p2.distanceTo(p1), CONSTANTS.wallConfig.height); - shape.lineTo(p2.distanceTo(p1), 0); - shape.lineTo(0, 0); - - const extrudeSettings = { - depth: CONSTANTS.wallConfig.width, - bevelEnabled: false - }; - const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); - const angle = Math.atan2(p2.z - p1.z, p2.x - p1.x); - Walls.push([geometry, [0, -angle, 0], [p1.x, (layer - 1) * CONSTANTS.wallConfig.height, p1.z], "RoomWall", layer]); - - wallSet.add(wallId); - } - } - }); - - ////////// Add Walls that are not forming any room ////////// - - lines.current.forEach(line => { - if (line[0][3] && line[1][3] !== CONSTANTS.lineConfig.wallName) { - return; - } - const [uuid1, uuid2] = line.map(point => point[1]); - let isInRoom = false; - const lineLayer = line[0][2]; - - for (let room of Rooms) { - const roomLayer = room.layer; - if (roomLayer !== lineLayer) continue; - for (let i = 0; i < room.coordinates.length - 1; i++) { - const roomUuid1 = room.coordinates[i].uuid; - const roomUuid2 = room.coordinates[(i + 1) % room.coordinates.length].uuid; - if ( - (uuid1 === roomUuid1 && uuid2 === roomUuid2) || - (uuid1 === roomUuid2 && uuid2 === roomUuid1) - ) { - isInRoom = true; - break; - } - } - if (isInRoom) break; - } - - if (!isInRoom) { - const p1 = new THREE.Vector3(line[0][0].x, 0, line[0][0].z); - const p2 = new THREE.Vector3(line[1][0].x, 0, line[1][0].z); - - let isCollinear = false; - for (let room of Rooms) { - if (room.layer !== lineLayer) continue; - for (let i = 0; i < room.coordinates.length - 1; i++) { - const roomP1 = room.coordinates[i].position; - const roomP2 = room.coordinates[(i + 1) % room.coordinates.length].position; - const lineFeature = turf.lineString([[p1.x, p1.z], [p2.x, p2.z]]); - const roomFeature = turf.lineString([[roomP1.x, roomP1.z], [roomP2.x, roomP2.z]]); - if (turf.booleanOverlap(lineFeature, roomFeature)) { - isCollinear = true; - break; - } - } - if (isCollinear) break; - } - - if (!isCollinear) { - const shape = new THREE.Shape(); - shape.moveTo(0, 0); - shape.lineTo(0, CONSTANTS.wallConfig.height); - shape.lineTo(p2.distanceTo(p1), CONSTANTS.wallConfig.height); - shape.lineTo(p2.distanceTo(p1), 0); - shape.lineTo(0, 0); - - const extrudeSettings = { - depth: CONSTANTS.wallConfig.width, - bevelEnabled: false - }; - const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); - const angle = Math.atan2(p2.z - p1.z, p2.x - p1.x); - Walls.push([geometry, [0, -angle, 0], [p1.x, (lineLayer - 1) * CONSTANTS.wallConfig.height, p1.z], "SegmentWall", lineLayer]); - } - } - }); - setWalls(Walls); - }else{ - setWalls([]); - } -} - -export default loadWalls; +import * as THREE from 'three'; +import * as turf from '@turf/turf'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; + +import * as Types from "../../../../types/world/worldTypes"; +import getRoomsFromLines from '../lines/getRoomsFromLines'; + +async function loadWalls( + lines: Types.RefLines, + setWalls: any, +): Promise { + ////////// Removes the old walls if any, Checks if there is any overlapping in lines if any updates it , starts function that creates floor and roof ////////// + + const Walls: Types.Walls = []; + const Rooms: Types.Rooms = []; + + localStorage.setItem("Lines", JSON.stringify(lines.current)); + + if (lines.current.length > 1) { + + ////////// Add Walls that are forming a room ////////// + + const wallSet = new Set(); + + const rooms: Types.Rooms = await getRoomsFromLines(lines); + Rooms.push(...rooms); + + Rooms.forEach(({ coordinates: room, layer }) => { + for (let i = 0; i < room.length - 1; i++) { + const uuid1 = room[i].uuid; + const uuid2 = room[(i + 1) % room.length].uuid; + const wallId = `${uuid1}_${uuid2}`; + + if (!wallSet.has(wallId)) { + const p1 = room[i].position; + const p2 = room[(i + 1) % room.length].position; + + const shape = new THREE.Shape(); + shape.moveTo(0, 0); + shape.lineTo(0, CONSTANTS.wallConfig.height); + shape.lineTo(p2.distanceTo(p1), CONSTANTS.wallConfig.height); + shape.lineTo(p2.distanceTo(p1), 0); + shape.lineTo(0, 0); + + const extrudeSettings = { + depth: CONSTANTS.wallConfig.width, + bevelEnabled: false + }; + const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); + const angle = Math.atan2(p2.z - p1.z, p2.x - p1.x); + Walls.push([geometry, [0, -angle, 0], [p1.x, (layer - 1) * CONSTANTS.wallConfig.height, p1.z], "RoomWall", layer]); + + wallSet.add(wallId); + } + } + }); + + ////////// Add Walls that are not forming any room ////////// + + lines.current.forEach(line => { + if (line[0][3] && line[1][3] !== CONSTANTS.lineConfig.wallName) { + return; + } + const [uuid1, uuid2] = line.map(point => point[1]); + let isInRoom = false; + const lineLayer = line[0][2]; + + for (let room of Rooms) { + const roomLayer = room.layer; + if (roomLayer !== lineLayer) continue; + for (let i = 0; i < room.coordinates.length - 1; i++) { + const roomUuid1 = room.coordinates[i].uuid; + const roomUuid2 = room.coordinates[(i + 1) % room.coordinates.length].uuid; + if ( + (uuid1 === roomUuid1 && uuid2 === roomUuid2) || + (uuid1 === roomUuid2 && uuid2 === roomUuid1) + ) { + isInRoom = true; + break; + } + } + if (isInRoom) break; + } + + if (!isInRoom) { + const p1 = new THREE.Vector3(line[0][0].x, 0, line[0][0].z); + const p2 = new THREE.Vector3(line[1][0].x, 0, line[1][0].z); + + let isCollinear = false; + for (let room of Rooms) { + if (room.layer !== lineLayer) continue; + for (let i = 0; i < room.coordinates.length - 1; i++) { + const roomP1 = room.coordinates[i].position; + const roomP2 = room.coordinates[(i + 1) % room.coordinates.length].position; + const lineFeature = turf.lineString([[p1.x, p1.z], [p2.x, p2.z]]); + const roomFeature = turf.lineString([[roomP1.x, roomP1.z], [roomP2.x, roomP2.z]]); + if (turf.booleanOverlap(lineFeature, roomFeature)) { + isCollinear = true; + break; + } + } + if (isCollinear) break; + } + + if (!isCollinear) { + const shape = new THREE.Shape(); + shape.moveTo(0, 0); + shape.lineTo(0, CONSTANTS.wallConfig.height); + shape.lineTo(p2.distanceTo(p1), CONSTANTS.wallConfig.height); + shape.lineTo(p2.distanceTo(p1), 0); + shape.lineTo(0, 0); + + const extrudeSettings = { + depth: CONSTANTS.wallConfig.width, + bevelEnabled: false + }; + const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); + const angle = Math.atan2(p2.z - p1.z, p2.x - p1.x); + Walls.push([geometry, [0, -angle, 0], [p1.x, (lineLayer - 1) * CONSTANTS.wallConfig.height, p1.z], "SegmentWall", lineLayer]); + } + } + }); + setWalls(Walls); + }else{ + setWalls([]); + } +} + +export default loadWalls; diff --git a/app/src/modules/builder/geomentries/zones/addZonesToScene.ts b/app/src/modules/builder/geomentries/zones/addZonesToScene.ts index 04316d6..6cfc22d 100644 --- a/app/src/modules/builder/geomentries/zones/addZonesToScene.ts +++ b/app/src/modules/builder/geomentries/zones/addZonesToScene.ts @@ -1,50 +1,50 @@ -import * as THREE from 'three'; -import * as Types from '../../../../types/world/worldTypes'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; - -const baseMaterial = new THREE.ShaderMaterial({ - side: THREE.DoubleSide, - vertexShader: ` - varying vec2 vUv; - void main(){ - gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); - vUv = uv; - } - `, - fragmentShader: ` - varying vec2 vUv; - uniform vec3 uColor; - void main(){ - float alpha = 1.0 - vUv.y; - gl_FragColor = vec4(uColor, alpha); - } - `, - uniforms: { - uColor: { value: new THREE.Color(CONSTANTS.zoneConfig.defaultColor) }, - }, - transparent: true, -}); - -export default function addZonesToScene( - line: Types.Line, - floorGroupZone: Types.RefGroup, - color: THREE.Color -) { - const point1 = line[0][0]; - const point2 = line[1][0]; - - const length = (new THREE.Vector3(point2.x, point2.y, point2.z)).distanceTo(new THREE.Vector3(point1.x, point1.y, point1.z)); - const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x); - - const geometry = new THREE.PlaneGeometry(length, 10); - - const material = baseMaterial.clone(); - material.uniforms.uColor.value.set(color.r, color.g, color.b); - - const mesh = new THREE.Mesh(geometry, material); - - mesh.position.set((point1.x + point2.x) / 2, ((line[0][2] - 1) * CONSTANTS.wallConfig.height) + 5, (point1.z + point2.z) / 2); - mesh.rotation.y = -angle; - - floorGroupZone.current.add(mesh); -} +import * as THREE from 'three'; +import * as Types from '../../../../types/world/worldTypes'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; + +const baseMaterial = new THREE.ShaderMaterial({ + side: THREE.DoubleSide, + vertexShader: ` + varying vec2 vUv; + void main(){ + gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); + vUv = uv; + } + `, + fragmentShader: ` + varying vec2 vUv; + uniform vec3 uColor; + void main(){ + float alpha = 1.0 - vUv.y; + gl_FragColor = vec4(uColor, alpha); + } + `, + uniforms: { + uColor: { value: new THREE.Color(CONSTANTS.zoneConfig.defaultColor) }, + }, + transparent: true, +}); + +export default function addZonesToScene( + line: Types.Line, + floorGroupZone: Types.RefGroup, + color: THREE.Color +) { + const point1 = line[0][0]; + const point2 = line[1][0]; + + const length = (new THREE.Vector3(point2.x, point2.y, point2.z)).distanceTo(new THREE.Vector3(point1.x, point1.y, point1.z)); + const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x); + + const geometry = new THREE.PlaneGeometry(length, 10); + + const material = baseMaterial.clone(); + material.uniforms.uColor.value.set(color.r, color.g, color.b); + + const mesh = new THREE.Mesh(geometry, material); + + mesh.position.set((point1.x + point2.x) / 2, ((line[0][2] - 1) * CONSTANTS.wallConfig.height) + 5, (point1.z + point2.z) / 2); + mesh.rotation.y = -angle; + + floorGroupZone.current.add(mesh); +} diff --git a/app/src/modules/builder/geomentries/zones/loadZones.ts b/app/src/modules/builder/geomentries/zones/loadZones.ts index b33aa44..aa78199 100644 --- a/app/src/modules/builder/geomentries/zones/loadZones.ts +++ b/app/src/modules/builder/geomentries/zones/loadZones.ts @@ -1,19 +1,19 @@ -import * as Types from '../../../../types/world/worldTypes'; -import * as THREE from 'three'; -import * as CONSTANTS from '../../../../types/world/worldConstants'; -import addZonesToScene from './addZonesToScene'; - -export default function loadZones( - lines: Types.RefLines, - floorGroupZone: Types.RefGroup -) { - if (!floorGroupZone.current) return - floorGroupZone.current.children = []; - const zones = lines.current.filter((line) => line[0][3] && line[1][3] === CONSTANTS.lineConfig.zoneName); - - if (zones.length > 0) { - zones.forEach((zone: Types.Line) => { - addZonesToScene(zone, floorGroupZone, new THREE.Color(CONSTANTS.zoneConfig.color)) - }) - } +import * as Types from '../../../../types/world/worldTypes'; +import * as THREE from 'three'; +import * as CONSTANTS from '../../../../types/world/worldConstants'; +import addZonesToScene from './addZonesToScene'; + +export default function loadZones( + lines: Types.RefLines, + floorGroupZone: Types.RefGroup +) { + if (!floorGroupZone.current) return + floorGroupZone.current.children = []; + const zones = lines.current.filter((line) => line[0][3] && line[1][3] === CONSTANTS.lineConfig.zoneName); + + if (zones.length > 0) { + zones.forEach((zone: Types.Line) => { + addZonesToScene(zone, floorGroupZone, new THREE.Color(CONSTANTS.zoneConfig.color)) + }) + } } \ No newline at end of file diff --git a/app/src/modules/builder/groups/floorGroup.tsx b/app/src/modules/builder/groups/floorGroup.tsx index a9daa2d..da3536b 100644 --- a/app/src/modules/builder/groups/floorGroup.tsx +++ b/app/src/modules/builder/groups/floorGroup.tsx @@ -1,101 +1,101 @@ -import { useFrame, useThree } from "@react-three/fiber"; -import { useAddAction, useDeleteModels, useRoofVisibility, useToggleView, useWallVisibility, useUpdateScene } from "../../../store/store"; -import hideRoof from "../geomentries/roofs/hideRoof"; -import hideWalls from "../geomentries/walls/hideWalls"; -import addAndUpdateReferencePillar from "../geomentries/pillars/addAndUpdateReferencePillar"; -import { useEffect } from "react"; -import addPillar from "../geomentries/pillars/addPillar"; -import DeletePillar from "../geomentries/pillars/deletePillar"; -import DeletableHoveredPillar from "../geomentries/pillars/deletableHoveredPillar"; -import loadFloor from "../geomentries/floors/loadFloor"; - -const FloorGroup = ({ floorGroup, lines, referencePole, hoveredDeletablePillar }: any) => { - const state = useThree(); - const { roofVisibility, setRoofVisibility } = useRoofVisibility(); - const { wallVisibility, setWallVisibility } = useWallVisibility(); - const { toggleView, setToggleView } = useToggleView(); - const { scene, camera, pointer, raycaster, gl } = useThree(); - const { addAction, setAddAction } = useAddAction(); - const { deleteModels, setDeleteModels } = useDeleteModels(); - const { updateScene, setUpdateScene } = useUpdateScene(); - - useEffect(() => { - if (updateScene) { - loadFloor(lines, floorGroup); - setUpdateScene(false); - } - }, [updateScene]) - - useEffect(() => { - if (!addAction) { - if (referencePole.current) { - (referencePole.current as any).material.dispose(); - (referencePole.current.geometry as any).dispose(); - floorGroup.current.remove(referencePole.current); - referencePole.current = undefined; - } - } - }, [addAction]); - - useEffect(() => { - const canvasElement = gl.domElement; - let drag = false; - let isLeftMouseDown = false; - - const onMouseDown = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = true; - drag = false; - } - }; - - const onMouseUp = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = false; - if (!drag) { - if (addAction === "pillar") { - addPillar(referencePole, floorGroup); - } - if (deleteModels) { - DeletePillar(hoveredDeletablePillar, floorGroup); - } - } - } - }; - - const onMouseMove = () => { - if (isLeftMouseDown) { - drag = true; - } - }; - - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - }; - }, [deleteModels, addAction]) - - useFrame(() => { - hideRoof(roofVisibility, floorGroup, camera); - hideWalls(wallVisibility, scene, camera); - - if (addAction === "pillar") { - addAndUpdateReferencePillar(raycaster, floorGroup, referencePole); - } - if (deleteModels) { - DeletableHoveredPillar(state, floorGroup, hoveredDeletablePillar); - } - }) - - return ( - - - ) -} - +import { useFrame, useThree } from "@react-three/fiber"; +import { useAddAction, useDeleteModels, useRoofVisibility, useToggleView, useWallVisibility, useUpdateScene } from "../../../store/store"; +import hideRoof from "../geomentries/roofs/hideRoof"; +import hideWalls from "../geomentries/walls/hideWalls"; +import addAndUpdateReferencePillar from "../geomentries/pillars/addAndUpdateReferencePillar"; +import { useEffect } from "react"; +import addPillar from "../geomentries/pillars/addPillar"; +import DeletePillar from "../geomentries/pillars/deletePillar"; +import DeletableHoveredPillar from "../geomentries/pillars/deletableHoveredPillar"; +import loadFloor from "../geomentries/floors/loadFloor"; + +const FloorGroup = ({ floorGroup, lines, referencePole, hoveredDeletablePillar }: any) => { + const state = useThree(); + const { roofVisibility, setRoofVisibility } = useRoofVisibility(); + const { wallVisibility, setWallVisibility } = useWallVisibility(); + const { toggleView, setToggleView } = useToggleView(); + const { scene, camera, pointer, raycaster, gl } = useThree(); + const { addAction, setAddAction } = useAddAction(); + const { deleteModels, setDeleteModels } = useDeleteModels(); + const { updateScene, setUpdateScene } = useUpdateScene(); + + useEffect(() => { + if (updateScene) { + loadFloor(lines, floorGroup); + setUpdateScene(false); + } + }, [updateScene]) + + useEffect(() => { + if (!addAction) { + if (referencePole.current) { + (referencePole.current as any).material.dispose(); + (referencePole.current.geometry as any).dispose(); + floorGroup.current.remove(referencePole.current); + referencePole.current = undefined; + } + } + }, [addAction]); + + useEffect(() => { + const canvasElement = gl.domElement; + let drag = false; + let isLeftMouseDown = false; + + const onMouseDown = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = true; + drag = false; + } + }; + + const onMouseUp = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = false; + if (!drag) { + if (addAction === "pillar") { + addPillar(referencePole, floorGroup); + } + if (deleteModels) { + DeletePillar(hoveredDeletablePillar, floorGroup); + } + } + } + }; + + const onMouseMove = () => { + if (isLeftMouseDown) { + drag = true; + } + }; + + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + }; + }, [deleteModels, addAction]) + + useFrame(() => { + hideRoof(roofVisibility, floorGroup, camera); + hideWalls(wallVisibility, scene, camera); + + if (addAction === "pillar") { + addAndUpdateReferencePillar(raycaster, floorGroup, referencePole); + } + if (deleteModels) { + DeletableHoveredPillar(state, floorGroup, hoveredDeletablePillar); + } + }) + + return ( + + + ) +} + export default FloorGroup; \ No newline at end of file diff --git a/app/src/modules/builder/groups/floorGroupAisle.tsx b/app/src/modules/builder/groups/floorGroupAisle.tsx index 3c32d65..23db1f5 100644 --- a/app/src/modules/builder/groups/floorGroupAisle.tsx +++ b/app/src/modules/builder/groups/floorGroupAisle.tsx @@ -1,245 +1,245 @@ -import * as THREE from 'three'; -import * as Types from '../../../types/world/worldTypes'; -import * as CONSTANTS from '../../../types/world/worldConstants'; -import { useThree } from "@react-three/fiber"; -import { useToggleView, useActiveLayer, useSocketStore, useDeletePointOrLine, useMovePoint, useUpdateScene, useNewLines, useToolMode } from "../../../store/store"; -import { useEffect } from "react"; -import removeSoloPoint from "../geomentries/points/removeSoloPoint"; -import removeReferenceLine from "../geomentries/lines/removeReferenceLine"; -import getClosestIntersection from "../geomentries/lines/getClosestIntersection"; -import addPointToScene from "../geomentries/points/addPointToScene"; -import arrayLineToObject from '../geomentries/lines/lineConvertions/arrayLineToObject'; -import addLineToScene from "../geomentries/lines/addLineToScene"; -import loadAisles from '../geomentries/aisles/loadAisles'; - - -const FloorGroupAilse = ({ floorGroupAisle, plane, floorPlanGroupLine, floorPlanGroupPoint, line, lines, currentLayerPoint, dragPointControls, floorPlanGroup, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => { - const { toggleView, setToggleView } = useToggleView(); - const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); - const { toolMode, setToolMode } = useToolMode(); - const { movePoint, setMovePoint } = useMovePoint(); - const { socket } = useSocketStore(); - const { activeLayer } = useActiveLayer(); - const { gl, raycaster, camera, pointer } = useThree(); - const { updateScene, setUpdateScene } = useUpdateScene(); - const { newLines, setNewLines } = useNewLines(); - - useEffect(() => { - if (updateScene) { - loadAisles(lines, floorGroupAisle); - setUpdateScene(false); - } - }, [updateScene]) - - useEffect(() => { - if (toolMode === "Aisle") { - setDeletePointOrLine(false); - setMovePoint(false); - } else { - removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); - removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); - } - }, [toolMode]); - - useEffect(() => { - - const canvasElement = gl.domElement; - - let drag = false; - let isLeftMouseDown = false; - - const onMouseDown = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = true; - drag = false; - } - }; - - const onMouseUp = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = false; - } - } - - const onMouseMove = () => { - if (isLeftMouseDown) { - drag = true; - } - }; - - const onContextMenu = (e: any) => { - e.preventDefault(); - if (toolMode === "Aisle") { - removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); - removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); - } - }; - - const onMouseClick = (evt: any) => { - if (!plane.current || drag) return; - - const intersects = raycaster.intersectObject(plane.current, true); - let intersectionPoint = intersects[0].point; - const points = floorPlanGroupPoint.current?.children ?? []; - const intersectsPoint = raycaster.intersectObjects(points, true).find(intersect => intersect.object.visible); - let intersectsLines: any = raycaster.intersectObjects(floorPlanGroupLine.current.children, true); - - - if (intersectsLines.length > 0 && intersects && intersects.length > 0 && !intersectsPoint) { - const lineType = intersectsLines[0].object.userData.linePoints[0][3]; - if (lineType === CONSTANTS.lineConfig.aisleName) { - // console.log("intersected a aisle line"); - const ThroughPoint = (intersectsLines[0].object.geometry.parameters.path).getPoints(CONSTANTS.lineConfig.lineIntersectionPoints); - let intersection = getClosestIntersection(ThroughPoint, intersectionPoint); - if (!intersection) return; - const point = addPointToScene(intersection, CONSTANTS.pointConfig.aisleOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.aisleName); - (line.current as Types.Line).push([new THREE.Vector3(intersection.x, 0.01, intersection.z), point.uuid, activeLayer, CONSTANTS.lineConfig.aisleName,]); - if (line.current.length >= 2 && line.current[0] && line.current[1]) { - lines.current.push(line.current as Types.Line); - - const data = arrayLineToObject(line.current as Types.Line); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setLine(organization, data.layer!, data.line!, data.type!); - - //SOCKET - - const input = { - organization: organization, - layer: data.layer, - line: data.line, - type: data.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input); - - setNewLines([line.current]); - - addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.pointConfig.aisleOuterColor, line.current, floorPlanGroupLine); - let lastPoint = line.current[line.current.length - 1]; - line.current = [lastPoint]; - } - } - } else if (intersectsPoint && intersects && intersects.length > 0) { - if (intersectsPoint.object.userData.type === CONSTANTS.lineConfig.aisleName) { - // console.log("intersected a aisle point"); - intersectionPoint = intersectsPoint.object.position; - (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), intersectsPoint.object.uuid, activeLayer, CONSTANTS.lineConfig.aisleName,]); - if (line.current.length >= 2 && line.current[0] && line.current[1]) { - lines.current.push(line.current as Types.Line); - - const data = arrayLineToObject(line.current as Types.Line); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setLine(organization, data.layer!, data.line!, data.type!); - - //SOCKET - - const input = { - organization: organization, - layer: data.layer, - line: data.line, - type: data.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input); - - setNewLines([line.current]); - - addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.pointConfig.aisleOuterColor, line.current, floorPlanGroupLine); - let lastPoint = line.current[line.current.length - 1]; - line.current = [lastPoint]; - ispreSnapped.current = false; - isSnapped.current = false; - } - } - } else if (intersects && intersects.length > 0) { - // console.log("intersected a empty area"); - let uuid: string = ""; - if (isAngleSnapped.current && anglesnappedPoint.current && line.current.length > 0) { - intersectionPoint = anglesnappedPoint.current; - const point = addPointToScene(intersectionPoint, CONSTANTS.pointConfig.aisleOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.aisleName); - uuid = point.uuid; - } else if (isSnapped.current && snappedPoint.current && line.current.length > 0) { - intersectionPoint = snappedPoint.current; - uuid = isSnappedUUID.current!; - } else if (ispreSnapped.current && snappedPoint.current) { - intersectionPoint = snappedPoint.current; - uuid = isSnappedUUID.current!; - } else { - const point = addPointToScene(intersectionPoint, CONSTANTS.pointConfig.aisleOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.aisleName); - uuid = point.uuid; - } - (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), uuid, activeLayer, CONSTANTS.lineConfig.aisleName,]); - - if (line.current.length >= 2 && line.current[0] && line.current[1]) { - lines.current.push(line.current as Types.Line); - - const data = arrayLineToObject(line.current as Types.Line); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setLine(organization, data.layer!, data.line!, data.type!); - - //SOCKET - - const input = { - organization: organization, - layer: data.layer, - line: data.line, - type: data.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input); - - setNewLines([line.current]); - - addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.pointConfig.aisleOuterColor, line.current, floorPlanGroupLine); - let lastPoint = line.current[line.current.length - 1]; - line.current = [lastPoint]; - ispreSnapped.current = false; - isSnapped.current = false; - } - } - } - - - if (toolMode === 'Aisle') { - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - canvasElement.addEventListener("click", onMouseClick); - canvasElement.addEventListener("contextmenu", onContextMenu); - } - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - canvasElement.removeEventListener("click", onMouseClick); - canvasElement.removeEventListener("contextmenu", onContextMenu); - }; - }, [toolMode]) - - - return ( - - - ) -} - +import * as THREE from 'three'; +import * as Types from '../../../types/world/worldTypes'; +import * as CONSTANTS from '../../../types/world/worldConstants'; +import { useThree } from "@react-three/fiber"; +import { useToggleView, useActiveLayer, useSocketStore, useDeletePointOrLine, useMovePoint, useUpdateScene, useNewLines, useToolMode } from "../../../store/store"; +import { useEffect } from "react"; +import removeSoloPoint from "../geomentries/points/removeSoloPoint"; +import removeReferenceLine from "../geomentries/lines/removeReferenceLine"; +import getClosestIntersection from "../geomentries/lines/getClosestIntersection"; +import addPointToScene from "../geomentries/points/addPointToScene"; +import arrayLineToObject from '../geomentries/lines/lineConvertions/arrayLineToObject'; +import addLineToScene from "../geomentries/lines/addLineToScene"; +import loadAisles from '../geomentries/aisles/loadAisles'; + + +const FloorGroupAilse = ({ floorGroupAisle, plane, floorPlanGroupLine, floorPlanGroupPoint, line, lines, currentLayerPoint, dragPointControls, floorPlanGroup, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => { + const { toggleView, setToggleView } = useToggleView(); + const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); + const { toolMode, setToolMode } = useToolMode(); + const { movePoint, setMovePoint } = useMovePoint(); + const { socket } = useSocketStore(); + const { activeLayer } = useActiveLayer(); + const { gl, raycaster, camera, pointer } = useThree(); + const { updateScene, setUpdateScene } = useUpdateScene(); + const { newLines, setNewLines } = useNewLines(); + + useEffect(() => { + if (updateScene) { + loadAisles(lines, floorGroupAisle); + setUpdateScene(false); + } + }, [updateScene]) + + useEffect(() => { + if (toolMode === "Aisle") { + setDeletePointOrLine(false); + setMovePoint(false); + } else { + removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); + removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); + } + }, [toolMode]); + + useEffect(() => { + + const canvasElement = gl.domElement; + + let drag = false; + let isLeftMouseDown = false; + + const onMouseDown = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = true; + drag = false; + } + }; + + const onMouseUp = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = false; + } + } + + const onMouseMove = () => { + if (isLeftMouseDown) { + drag = true; + } + }; + + const onContextMenu = (e: any) => { + e.preventDefault(); + if (toolMode === "Aisle") { + removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); + removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); + } + }; + + const onMouseClick = (evt: any) => { + if (!plane.current || drag) return; + + const intersects = raycaster.intersectObject(plane.current, true); + let intersectionPoint = intersects[0].point; + const points = floorPlanGroupPoint.current?.children ?? []; + const intersectsPoint = raycaster.intersectObjects(points, true).find(intersect => intersect.object.visible); + let intersectsLines: any = raycaster.intersectObjects(floorPlanGroupLine.current.children, true); + + + if (intersectsLines.length > 0 && intersects && intersects.length > 0 && !intersectsPoint) { + const lineType = intersectsLines[0].object.userData.linePoints[0][3]; + if (lineType === CONSTANTS.lineConfig.aisleName) { + // console.log("intersected a aisle line"); + const ThroughPoint = (intersectsLines[0].object.geometry.parameters.path).getPoints(CONSTANTS.lineConfig.lineIntersectionPoints); + let intersection = getClosestIntersection(ThroughPoint, intersectionPoint); + if (!intersection) return; + const point = addPointToScene(intersection, CONSTANTS.pointConfig.aisleOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.aisleName); + (line.current as Types.Line).push([new THREE.Vector3(intersection.x, 0.01, intersection.z), point.uuid, activeLayer, CONSTANTS.lineConfig.aisleName,]); + if (line.current.length >= 2 && line.current[0] && line.current[1]) { + lines.current.push(line.current as Types.Line); + + const data = arrayLineToObject(line.current as Types.Line); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setLine(organization, data.layer!, data.line!, data.type!); + + //SOCKET + + const input = { + organization: organization, + layer: data.layer, + line: data.line, + type: data.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input); + + setNewLines([line.current]); + + addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.pointConfig.aisleOuterColor, line.current, floorPlanGroupLine); + let lastPoint = line.current[line.current.length - 1]; + line.current = [lastPoint]; + } + } + } else if (intersectsPoint && intersects && intersects.length > 0) { + if (intersectsPoint.object.userData.type === CONSTANTS.lineConfig.aisleName) { + // console.log("intersected a aisle point"); + intersectionPoint = intersectsPoint.object.position; + (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), intersectsPoint.object.uuid, activeLayer, CONSTANTS.lineConfig.aisleName,]); + if (line.current.length >= 2 && line.current[0] && line.current[1]) { + lines.current.push(line.current as Types.Line); + + const data = arrayLineToObject(line.current as Types.Line); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setLine(organization, data.layer!, data.line!, data.type!); + + //SOCKET + + const input = { + organization: organization, + layer: data.layer, + line: data.line, + type: data.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input); + + setNewLines([line.current]); + + addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.pointConfig.aisleOuterColor, line.current, floorPlanGroupLine); + let lastPoint = line.current[line.current.length - 1]; + line.current = [lastPoint]; + ispreSnapped.current = false; + isSnapped.current = false; + } + } + } else if (intersects && intersects.length > 0) { + // console.log("intersected a empty area"); + let uuid: string = ""; + if (isAngleSnapped.current && anglesnappedPoint.current && line.current.length > 0) { + intersectionPoint = anglesnappedPoint.current; + const point = addPointToScene(intersectionPoint, CONSTANTS.pointConfig.aisleOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.aisleName); + uuid = point.uuid; + } else if (isSnapped.current && snappedPoint.current && line.current.length > 0) { + intersectionPoint = snappedPoint.current; + uuid = isSnappedUUID.current!; + } else if (ispreSnapped.current && snappedPoint.current) { + intersectionPoint = snappedPoint.current; + uuid = isSnappedUUID.current!; + } else { + const point = addPointToScene(intersectionPoint, CONSTANTS.pointConfig.aisleOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.aisleName); + uuid = point.uuid; + } + (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), uuid, activeLayer, CONSTANTS.lineConfig.aisleName,]); + + if (line.current.length >= 2 && line.current[0] && line.current[1]) { + lines.current.push(line.current as Types.Line); + + const data = arrayLineToObject(line.current as Types.Line); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setLine(organization, data.layer!, data.line!, data.type!); + + //SOCKET + + const input = { + organization: organization, + layer: data.layer, + line: data.line, + type: data.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input); + + setNewLines([line.current]); + + addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.pointConfig.aisleOuterColor, line.current, floorPlanGroupLine); + let lastPoint = line.current[line.current.length - 1]; + line.current = [lastPoint]; + ispreSnapped.current = false; + isSnapped.current = false; + } + } + } + + + if (toolMode === 'Aisle') { + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + canvasElement.addEventListener("click", onMouseClick); + canvasElement.addEventListener("contextmenu", onContextMenu); + } + + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + canvasElement.removeEventListener("click", onMouseClick); + canvasElement.removeEventListener("contextmenu", onContextMenu); + }; + }, [toolMode]) + + + return ( + + + ) +} + export default FloorGroupAilse; \ No newline at end of file diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx index 155f8e8..033146d 100644 --- a/app/src/modules/builder/groups/floorItemsGroup.tsx +++ b/app/src/modules/builder/groups/floorItemsGroup.tsx @@ -1,292 +1,292 @@ -import { useFrame, useThree } from "@react-three/fiber"; -import { useActiveTool, useCamMode, useDeletableFloorItem, useDeleteModels, useFloorItems, useRenderDistance, useselectedFloorItem, useSelectedItem, useSocketStore, useToggleView, useTransformMode } from "../../../store/store"; -import assetVisibility from "../geomentries/assets/assetVisibility"; -import { useEffect } from "react"; -import * as THREE from "three"; -import * as Types from "../../../types/world/worldTypes"; -import assetManager, { cancelOngoingTasks } from "../geomentries/assets/assetManager"; -import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; -import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; -import DeletableHoveredFloorItems from "../geomentries/assets/deletableHoveredFloorItems"; -import DeleteFloorItems from "../geomentries/assets/deleteFloorItems"; -import loadInitialFloorItems from "../../scene/IntialLoad/loadInitialFloorItems"; -import addAssetModel from "../geomentries/assets/addAssetModel"; -// import { getFloorItems } from "../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi"; -// import { retrieveGLTF } from "../../../utils/indexDB/idbUtils"; -const assetManagerWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/assetManagerWorker.js', import.meta.url)); -// const gltfLoaderWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js', import.meta.url)); - -const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject, floorGroup, tempLoader, isTempLoader, plane }: any) => { - const state: Types.ThreeState = useThree(); - const { raycaster, camera, controls, pointer }: any = state; - const { renderDistance, setRenderDistance } = useRenderDistance(); - const { toggleView, setToggleView } = useToggleView(); - const { floorItems, setFloorItems } = useFloorItems(); - const { camMode, setCamMode } = useCamMode(); - const { deleteModels, setDeleteModels } = useDeleteModels(); - const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem(); - const { transformMode, setTransformMode } = useTransformMode(); - const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem(); - const { activeTool, setActiveTool } = useActiveTool(); - const { selectedItem, setSelectedItem } = useSelectedItem(); - const { socket } = useSocketStore(); - - const loader = new GLTFLoader(); - const dracoLoader = new DRACOLoader(); - - dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); - loader.setDRACOLoader(dracoLoader); - - useEffect(() => { - // Load initial floor items - - // const email = localStorage.getItem('email'); - // const organization = (email!.split("@")[1]).split(".")[0]; - - // getFloorItems(organization).then((data) => { - // gltfLoaderWorker.postMessage({ FloorItems: data }) - // }) - - // gltfLoaderWorker.onmessage = async (event) => { - // if (event.data.message === "gltfLoaded" && event.data.modelBlob) { - // const blobUrl = URL.createObjectURL(event.data.modelBlob); - - // loader.load(blobUrl, (gltf) => { - // URL.revokeObjectURL(blobUrl); - // THREE.Cache.remove(blobUrl); - // THREE.Cache.add(event.data.modelID, gltf); - // }); - - // } else if (event.data.message === "done") { - // loadInitialFloorItems(itemsGroup, setFloorItems); - // } - // } - - - loadInitialFloorItems(itemsGroup, setFloorItems); - }, []); - - useEffect(() => { - assetManagerWorker.onmessage = async (event) => { - cancelOngoingTasks(); // Cancel the ongoing process - await assetManager(event.data, itemsGroup, loader); - }; - }, [assetManagerWorker]); - - useEffect(() => { - if (toggleView) return - - const uuids: string[] = []; - itemsGroup.current?.children.forEach((child: any) => { - uuids.push(child.uuid); - }); - const cameraPosition = state.camera.position; - - assetManagerWorker.postMessage({ floorItems, cameraPosition, uuids, renderDistance }); - }, [camMode, renderDistance]); - - useEffect(() => { - const controls: any = state.controls; - const camera: any = state.camera; - - if (controls) { - let intervalId: NodeJS.Timeout | null = null; - - const handleChange = () => { - if (toggleView) return - - const uuids: string[] = []; - itemsGroup.current?.children.forEach((child: any) => { - uuids.push(child.uuid); - }); - const cameraPosition = camera.position; - - assetManagerWorker.postMessage({ floorItems, cameraPosition, uuids, renderDistance }); - }; - - const startInterval = () => { - if (!intervalId) { - intervalId = setInterval(handleChange, 50); - } - }; - - const stopInterval = () => { - handleChange(); - if (intervalId) { - clearInterval(intervalId); - intervalId = null; - } - }; - - controls.addEventListener('rest', handleChange); - controls.addEventListener('rest', stopInterval); - controls.addEventListener('control', startInterval); - controls.addEventListener('controlend', stopInterval); - - return () => { - controls.removeEventListener('rest', handleChange); - controls.removeEventListener('rest', stopInterval); - controls.removeEventListener('control', startInterval); - controls.removeEventListener('controlend', stopInterval); - if (intervalId) { - clearInterval(intervalId); - } - }; - } - }, [state.controls, floorItems, toggleView, renderDistance]); - - useEffect(() => { - const canvasElement = state.gl.domElement; - let drag = false; - let isLeftMouseDown = false; - - const onMouseDown = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = true; - drag = false; - } - }; - - const onMouseMove = () => { - if (isLeftMouseDown) { - drag = true; - } - }; - - const onMouseUp = async (evt: any) => { - if (controls) { - (controls as any).enabled = true; - } - if (evt.button === 0) { - isLeftMouseDown = false; - if (drag) return; - - if (deleteModels) { - DeleteFloorItems(itemsGroup, hoveredDeletableFloorItem, setFloorItems, socket); - } - const Mode = transformMode; - - if (Mode !== null || activeTool === "Cursor") { - if (!itemsGroup.current) return; - let intersects = raycaster.intersectObjects(itemsGroup.current.children, true); - if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) { - // let currentObject = intersects[0].object; - - // while (currentObject) { - // if (currentObject.name === "Scene") { - // break; - // } - // currentObject = currentObject.parent as THREE.Object3D; - // } - // if (currentObject) { - // AttachedObject.current = currentObject as any; - // setselectedFloorItem(AttachedObject.current!); - // } - } else { - const target = controls.getTarget(new THREE.Vector3()); - await controls.setTarget(target.x, 0, target.z, true); - setselectedFloorItem(null); - } - } - } - }; - - const onDblClick = async (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = false; - if (drag) return; - - const Mode = transformMode; - - if (Mode !== null || activeTool === "Cursor") { - if (!itemsGroup.current) return; - let intersects = raycaster.intersectObjects(itemsGroup.current.children, true); - if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) { - let currentObject = intersects[0].object; - - while (currentObject) { - if (currentObject.name === "Scene") { - break; - } - currentObject = currentObject.parent as THREE.Object3D; - } - if (currentObject) { - AttachedObject.current = currentObject as any; - // controls.fitToSphere(AttachedObject.current!, true); - - const bbox = new THREE.Box3().setFromObject(AttachedObject.current); - const size = bbox.getSize(new THREE.Vector3()); - const center = bbox.getCenter(new THREE.Vector3()); - - const front = new THREE.Vector3(0, 0, 1); - AttachedObject.current.localToWorld(front); - front.sub(AttachedObject.current.position).normalize(); - - const distance = Math.max(size.x, size.y, size.z) * 2; - const newPosition = center.clone().addScaledVector(front, distance); - - controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true); - controls.setTarget(center.x, center.y, center.z, true); - controls.fitToBox(AttachedObject.current!, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5 }); - - setselectedFloorItem(AttachedObject.current!); - } - } else { - const target = controls.getTarget(new THREE.Vector3()); - await controls.setTarget(target.x, 0, target.z, true); - setselectedFloorItem(null); - } - } - } - } - - const onDrop = (event: any) => { - - if (!event.dataTransfer?.files[0]) return; - - if (selectedItem.id !== "" && event.dataTransfer?.files[0]) { - addAssetModel(raycaster, state.camera, state.pointer, floorGroup, setFloorItems, itemsGroup, isTempLoader, tempLoader, socket, selectedItem, setSelectedItem, plane); - } - } - - const onDragOver = (event: any) => { - event.preventDefault(); - }; - - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - canvasElement.addEventListener("dblclick", onDblClick); - canvasElement.addEventListener("drop", onDrop); - canvasElement.addEventListener("dragover", onDragOver); - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - canvasElement.removeEventListener("dblclick", onDblClick); - canvasElement.removeEventListener("drop", onDrop); - canvasElement.removeEventListener("dragover", onDragOver); - }; - }, [deleteModels, transformMode, controls, selectedItem, state.camera, state.pointer, activeTool]); - - useFrame(() => { - if (controls) - assetVisibility(itemsGroup, state.camera.position, renderDistance); - if (deleteModels) { - DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem); - } else if (!deleteModels) { - if (hoveredDeletableFloorItem.current) { - hoveredDeletableFloorItem.current = undefined; - setDeletableFloorItem(null); - } - } - }) - - return ( - - - ) -} - +import { useFrame, useThree } from "@react-three/fiber"; +import { useActiveTool, useCamMode, useDeletableFloorItem, useDeleteModels, useFloorItems, useRenderDistance, useselectedFloorItem, useSelectedItem, useSocketStore, useToggleView, useTransformMode } from "../../../store/store"; +import assetVisibility from "../geomentries/assets/assetVisibility"; +import { useEffect } from "react"; +import * as THREE from "three"; +import * as Types from "../../../types/world/worldTypes"; +import assetManager, { cancelOngoingTasks } from "../geomentries/assets/assetManager"; +import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; +import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; +import DeletableHoveredFloorItems from "../geomentries/assets/deletableHoveredFloorItems"; +import DeleteFloorItems from "../geomentries/assets/deleteFloorItems"; +import loadInitialFloorItems from "../../scene/IntialLoad/loadInitialFloorItems"; +import addAssetModel from "../geomentries/assets/addAssetModel"; +// import { getFloorItems } from "../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi"; +// import { retrieveGLTF } from "../../../utils/indexDB/idbUtils"; +const assetManagerWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/assetManagerWorker.js', import.meta.url)); +// const gltfLoaderWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js', import.meta.url)); + +const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject, floorGroup, tempLoader, isTempLoader, plane }: any) => { + const state: Types.ThreeState = useThree(); + const { raycaster, camera, controls, pointer }: any = state; + const { renderDistance, setRenderDistance } = useRenderDistance(); + const { toggleView, setToggleView } = useToggleView(); + const { floorItems, setFloorItems } = useFloorItems(); + const { camMode, setCamMode } = useCamMode(); + const { deleteModels, setDeleteModels } = useDeleteModels(); + const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem(); + const { transformMode, setTransformMode } = useTransformMode(); + const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem(); + const { activeTool, setActiveTool } = useActiveTool(); + const { selectedItem, setSelectedItem } = useSelectedItem(); + const { socket } = useSocketStore(); + + const loader = new GLTFLoader(); + const dracoLoader = new DRACOLoader(); + + dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); + loader.setDRACOLoader(dracoLoader); + + useEffect(() => { + // Load initial floor items + + // const email = localStorage.getItem('email'); + // const organization = (email!.split("@")[1]).split(".")[0]; + + // getFloorItems(organization).then((data) => { + // gltfLoaderWorker.postMessage({ FloorItems: data }) + // }) + + // gltfLoaderWorker.onmessage = async (event) => { + // if (event.data.message === "gltfLoaded" && event.data.modelBlob) { + // const blobUrl = URL.createObjectURL(event.data.modelBlob); + + // loader.load(blobUrl, (gltf) => { + // URL.revokeObjectURL(blobUrl); + // THREE.Cache.remove(blobUrl); + // THREE.Cache.add(event.data.modelID, gltf); + // }); + + // } else if (event.data.message === "done") { + // loadInitialFloorItems(itemsGroup, setFloorItems); + // } + // } + + + loadInitialFloorItems(itemsGroup, setFloorItems); + }, []); + + useEffect(() => { + assetManagerWorker.onmessage = async (event) => { + cancelOngoingTasks(); // Cancel the ongoing process + await assetManager(event.data, itemsGroup, loader); + }; + }, [assetManagerWorker]); + + useEffect(() => { + if (toggleView) return + + const uuids: string[] = []; + itemsGroup.current?.children.forEach((child: any) => { + uuids.push(child.uuid); + }); + const cameraPosition = state.camera.position; + + assetManagerWorker.postMessage({ floorItems, cameraPosition, uuids, renderDistance }); + }, [camMode, renderDistance]); + + useEffect(() => { + const controls: any = state.controls; + const camera: any = state.camera; + + if (controls) { + let intervalId: NodeJS.Timeout | null = null; + + const handleChange = () => { + if (toggleView) return + + const uuids: string[] = []; + itemsGroup.current?.children.forEach((child: any) => { + uuids.push(child.uuid); + }); + const cameraPosition = camera.position; + + assetManagerWorker.postMessage({ floorItems, cameraPosition, uuids, renderDistance }); + }; + + const startInterval = () => { + if (!intervalId) { + intervalId = setInterval(handleChange, 50); + } + }; + + const stopInterval = () => { + handleChange(); + if (intervalId) { + clearInterval(intervalId); + intervalId = null; + } + }; + + controls.addEventListener('rest', handleChange); + controls.addEventListener('rest', stopInterval); + controls.addEventListener('control', startInterval); + controls.addEventListener('controlend', stopInterval); + + return () => { + controls.removeEventListener('rest', handleChange); + controls.removeEventListener('rest', stopInterval); + controls.removeEventListener('control', startInterval); + controls.removeEventListener('controlend', stopInterval); + if (intervalId) { + clearInterval(intervalId); + } + }; + } + }, [state.controls, floorItems, toggleView, renderDistance]); + + useEffect(() => { + const canvasElement = state.gl.domElement; + let drag = false; + let isLeftMouseDown = false; + + const onMouseDown = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = true; + drag = false; + } + }; + + const onMouseMove = () => { + if (isLeftMouseDown) { + drag = true; + } + }; + + const onMouseUp = async (evt: any) => { + if (controls) { + (controls as any).enabled = true; + } + if (evt.button === 0) { + isLeftMouseDown = false; + if (drag) return; + + if (deleteModels) { + DeleteFloorItems(itemsGroup, hoveredDeletableFloorItem, setFloorItems, socket); + } + const Mode = transformMode; + + if (Mode !== null || activeTool === "Cursor") { + if (!itemsGroup.current) return; + let intersects = raycaster.intersectObjects(itemsGroup.current.children, true); + if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) { + // let currentObject = intersects[0].object; + + // while (currentObject) { + // if (currentObject.name === "Scene") { + // break; + // } + // currentObject = currentObject.parent as THREE.Object3D; + // } + // if (currentObject) { + // AttachedObject.current = currentObject as any; + // setselectedFloorItem(AttachedObject.current!); + // } + } else { + const target = controls.getTarget(new THREE.Vector3()); + await controls.setTarget(target.x, 0, target.z, true); + setselectedFloorItem(null); + } + } + } + }; + + const onDblClick = async (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = false; + if (drag) return; + + const Mode = transformMode; + + if (Mode !== null || activeTool === "Cursor") { + if (!itemsGroup.current) return; + let intersects = raycaster.intersectObjects(itemsGroup.current.children, true); + if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) { + let currentObject = intersects[0].object; + + while (currentObject) { + if (currentObject.name === "Scene") { + break; + } + currentObject = currentObject.parent as THREE.Object3D; + } + if (currentObject) { + AttachedObject.current = currentObject as any; + // controls.fitToSphere(AttachedObject.current!, true); + + const bbox = new THREE.Box3().setFromObject(AttachedObject.current); + const size = bbox.getSize(new THREE.Vector3()); + const center = bbox.getCenter(new THREE.Vector3()); + + const front = new THREE.Vector3(0, 0, 1); + AttachedObject.current.localToWorld(front); + front.sub(AttachedObject.current.position).normalize(); + + const distance = Math.max(size.x, size.y, size.z) * 2; + const newPosition = center.clone().addScaledVector(front, distance); + + controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true); + controls.setTarget(center.x, center.y, center.z, true); + controls.fitToBox(AttachedObject.current!, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5 }); + + setselectedFloorItem(AttachedObject.current!); + } + } else { + const target = controls.getTarget(new THREE.Vector3()); + await controls.setTarget(target.x, 0, target.z, true); + setselectedFloorItem(null); + } + } + } + } + + const onDrop = (event: any) => { + + if (!event.dataTransfer?.files[0]) return; + + if (selectedItem.id !== "" && event.dataTransfer?.files[0]) { + addAssetModel(raycaster, state.camera, state.pointer, floorGroup, setFloorItems, itemsGroup, isTempLoader, tempLoader, socket, selectedItem, setSelectedItem, plane); + } + } + + const onDragOver = (event: any) => { + event.preventDefault(); + }; + + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + canvasElement.addEventListener("dblclick", onDblClick); + canvasElement.addEventListener("drop", onDrop); + canvasElement.addEventListener("dragover", onDragOver); + + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + canvasElement.removeEventListener("dblclick", onDblClick); + canvasElement.removeEventListener("drop", onDrop); + canvasElement.removeEventListener("dragover", onDragOver); + }; + }, [deleteModels, transformMode, controls, selectedItem, state.camera, state.pointer, activeTool]); + + useFrame(() => { + if (controls) + assetVisibility(itemsGroup, state.camera.position, renderDistance); + if (deleteModels) { + DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem); + } else if (!deleteModels) { + if (hoveredDeletableFloorItem.current) { + hoveredDeletableFloorItem.current = undefined; + setDeletableFloorItem(null); + } + } + }) + + return ( + + + ) +} + export default FloorItemsGroup; \ No newline at end of file diff --git a/app/src/modules/builder/groups/floorPlanGroup.tsx b/app/src/modules/builder/groups/floorPlanGroup.tsx index a767f34..6369e1e 100644 --- a/app/src/modules/builder/groups/floorPlanGroup.tsx +++ b/app/src/modules/builder/groups/floorPlanGroup.tsx @@ -1,197 +1,197 @@ -import { useEffect } from "react"; -import * as Types from '../../../types/world/worldTypes'; -import { useActiveLayer, useDeletedLines, useDeletePointOrLine, useToolMode, useMovePoint, useNewLines, useRemovedLayer, useSocketStore, useToggleView, useUpdateScene } from "../../../store/store"; -import Layer2DVisibility from "../geomentries/layers/layer2DVisibility"; -import { useFrame, useThree } from "@react-three/fiber"; -import DeletableLineorPoint from "../functions/deletableLineOrPoint"; -import removeSoloPoint from "../geomentries/points/removeSoloPoint"; -import removeReferenceLine from "../geomentries/lines/removeReferenceLine"; -import DeleteLayer from "../geomentries/layers/deleteLayer"; -import { getLines } from "../../../services/factoryBuilder/lines/getLinesApi"; -import objectLinesToArray from "../geomentries/lines/lineConvertions/objectLinesToArray"; -import loadInitialPoint from "../../scene/IntialLoad/loadInitialPoint"; -import loadInitialLine from "../../scene/IntialLoad/loadInitialLine"; -import deletePoint from "../geomentries/points/deletePoint"; -import deleteLine from "../geomentries/lines/deleteLine"; -import drawWall from "../geomentries/lines/drawWall"; -import drawOnlyFloor from "../geomentries/floors/drawOnlyFloor"; -import addDragControl from "../eventDeclaration/dragControlDeclaration"; - - -const FloorPlanGroup = ({ floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, floorGroup, currentLayerPoint, dragPointControls, hoveredDeletablePoint, hoveredDeletableLine, plane, line, lines, onlyFloorline, onlyFloorlines, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => { - const state = useThree(); - const { scene, camera, gl, raycaster, controls } = state; - const { activeLayer, setActiveLayer } = useActiveLayer(); - const { toggleView, setToggleView } = useToggleView(); - const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); - const { toolMode, setToolMode } = useToolMode(); - const { movePoint, setMovePoint } = useMovePoint(); - const { removedLayer, setRemovedLayer } = useRemovedLayer(); - const { updateScene, setUpdateScene } = useUpdateScene(); - const { newLines, setNewLines } = useNewLines(); - const { deletedLines, setDeletedLines } = useDeletedLines(); - const { socket } = useSocketStore(); - - useEffect(() => { - addDragControl(dragPointControls, currentLayerPoint, state, floorPlanGroupPoint, floorPlanGroupLine, lines, onlyFloorlines, socket); - }, [state]); - - useEffect(() => { - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - // Load data from localStorage if available - getLines(organization).then((data) => { - - const Lines: Types.Lines = objectLinesToArray(data); - - // const data = localStorage.getItem("Lines"); - - if (Lines) { - lines.current = Lines; - loadInitialPoint(lines, floorPlanGroupPoint, currentLayerPoint, dragPointControls); - loadInitialLine(floorPlanGroupLine, lines); - setUpdateScene(true); - } - }) - }, []); - - useEffect(() => { - if (!toggleView) { - removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); - removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); - } - }, [toggleView]); - - useEffect(() => { - if (toolMode === "Wall" || toolMode === "Floor") { - setDeletePointOrLine(false); - setMovePoint(false); - } else { - removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); - removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); - } - }, [toolMode]); - - useEffect(() => { - if (movePoint) { - setToolMode(null); - setDeletePointOrLine(false); - if (dragPointControls.current) { - dragPointControls.current.enabled = true; - } - } else { - if (dragPointControls.current) { - dragPointControls.current.enabled = false; - } - } - }, [movePoint, toolMode]); - - useEffect(() => { - if (deletePointOrLine) { - setToolMode(null); - setMovePoint(false); - } - }, [deletePointOrLine]); - - useEffect(() => { - Layer2DVisibility(activeLayer, floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, currentLayerPoint, dragPointControls); - }, [activeLayer]); - - useEffect(() => { - if (removedLayer !== null) { - DeleteLayer(removedLayer, lines, floorPlanGroupLine, floorPlanGroupPoint, onlyFloorlines, floorGroup, setDeletedLines, setRemovedLayer, socket); - } - }, [removedLayer]); - - useEffect(() => { - - const canvasElement = gl.domElement; - - let drag = false; - let isLeftMouseDown = false; - - const onMouseDown = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = true; - drag = false; - } - }; - - const onMouseUp = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = false; - } - if (controls) { - (controls as any).enabled = true; - } - } - - const onMouseMove = () => { - if (isLeftMouseDown) { - drag = true; - } - }; - - const onContextMenu = (e: any) => { - e.preventDefault(); - if (toolMode === "Wall" || toolMode === "Floor") { - removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); - removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); - } - }; - - const onMouseClick = (evt: any) => { - if (!plane.current || drag) return; - - if (deletePointOrLine) { - if (hoveredDeletablePoint.current !== null) { - deletePoint(hoveredDeletablePoint, onlyFloorlines, floorPlanGroupPoint, floorPlanGroupLine, lines, setDeletedLines, socket); - } - if (hoveredDeletableLine.current !== null) { - deleteLine(hoveredDeletableLine, onlyFloorlines, lines, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, socket); - } - } - - if (toolMode === "Wall") { - drawWall(raycaster, plane, floorPlanGroupPoint, snappedPoint, isSnapped, isSnappedUUID, line, ispreSnapped, anglesnappedPoint, isAngleSnapped, lines, floorPlanGroupLine, floorPlanGroup, ReferenceLineMesh, LineCreated, currentLayerPoint, dragPointControls, setNewLines, setDeletedLines, activeLayer, socket); - } - - if (toolMode === "Floor") { - drawOnlyFloor(raycaster, state, camera, plane, floorPlanGroupPoint, snappedPoint, isSnapped, isSnappedUUID, line, ispreSnapped, anglesnappedPoint, isAngleSnapped, onlyFloorline, onlyFloorlines, lines, floorPlanGroupLine, floorPlanGroup, ReferenceLineMesh, LineCreated, currentLayerPoint, dragPointControls, setNewLines, setDeletedLines, activeLayer, socket); - } - } - - if (deletePointOrLine || toolMode === "Wall" || toolMode === "Floor") { - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - canvasElement.addEventListener("click", onMouseClick); - canvasElement.addEventListener("contextmenu", onContextMenu); - } - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - canvasElement.removeEventListener("click", onMouseClick); - canvasElement.removeEventListener("contextmenu", onContextMenu); - }; - }, [deletePointOrLine, toolMode, activeLayer]) - - - useFrame(() => { - if (deletePointOrLine) { - DeletableLineorPoint(state, plane, floorPlanGroupLine, floorPlanGroupPoint, hoveredDeletableLine, hoveredDeletablePoint); - } - }) - - return ( - - - - - ) -} - +import { useEffect } from "react"; +import * as Types from '../../../types/world/worldTypes'; +import { useActiveLayer, useDeletedLines, useDeletePointOrLine, useToolMode, useMovePoint, useNewLines, useRemovedLayer, useSocketStore, useToggleView, useUpdateScene } from "../../../store/store"; +import Layer2DVisibility from "../geomentries/layers/layer2DVisibility"; +import { useFrame, useThree } from "@react-three/fiber"; +import DeletableLineorPoint from "../functions/deletableLineOrPoint"; +import removeSoloPoint from "../geomentries/points/removeSoloPoint"; +import removeReferenceLine from "../geomentries/lines/removeReferenceLine"; +import DeleteLayer from "../geomentries/layers/deleteLayer"; +import { getLines } from "../../../services/factoryBuilder/lines/getLinesApi"; +import objectLinesToArray from "../geomentries/lines/lineConvertions/objectLinesToArray"; +import loadInitialPoint from "../../scene/IntialLoad/loadInitialPoint"; +import loadInitialLine from "../../scene/IntialLoad/loadInitialLine"; +import deletePoint from "../geomentries/points/deletePoint"; +import deleteLine from "../geomentries/lines/deleteLine"; +import drawWall from "../geomentries/lines/drawWall"; +import drawOnlyFloor from "../geomentries/floors/drawOnlyFloor"; +import addDragControl from "../eventDeclaration/dragControlDeclaration"; + + +const FloorPlanGroup = ({ floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, floorGroup, currentLayerPoint, dragPointControls, hoveredDeletablePoint, hoveredDeletableLine, plane, line, lines, onlyFloorline, onlyFloorlines, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => { + const state = useThree(); + const { scene, camera, gl, raycaster, controls } = state; + const { activeLayer, setActiveLayer } = useActiveLayer(); + const { toggleView, setToggleView } = useToggleView(); + const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); + const { toolMode, setToolMode } = useToolMode(); + const { movePoint, setMovePoint } = useMovePoint(); + const { removedLayer, setRemovedLayer } = useRemovedLayer(); + const { updateScene, setUpdateScene } = useUpdateScene(); + const { newLines, setNewLines } = useNewLines(); + const { deletedLines, setDeletedLines } = useDeletedLines(); + const { socket } = useSocketStore(); + + useEffect(() => { + addDragControl(dragPointControls, currentLayerPoint, state, floorPlanGroupPoint, floorPlanGroupLine, lines, onlyFloorlines, socket); + }, [state]); + + useEffect(() => { + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + // Load data from localStorage if available + getLines(organization).then((data) => { + + const Lines: Types.Lines = objectLinesToArray(data); + + // const data = localStorage.getItem("Lines"); + + if (Lines) { + lines.current = Lines; + loadInitialPoint(lines, floorPlanGroupPoint, currentLayerPoint, dragPointControls); + loadInitialLine(floorPlanGroupLine, lines); + setUpdateScene(true); + } + }) + }, []); + + useEffect(() => { + if (!toggleView) { + removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); + removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); + } + }, [toggleView]); + + useEffect(() => { + if (toolMode === "Wall" || toolMode === "Floor") { + setDeletePointOrLine(false); + setMovePoint(false); + } else { + removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); + removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); + } + }, [toolMode]); + + useEffect(() => { + if (movePoint) { + setToolMode(null); + setDeletePointOrLine(false); + if (dragPointControls.current) { + dragPointControls.current.enabled = true; + } + } else { + if (dragPointControls.current) { + dragPointControls.current.enabled = false; + } + } + }, [movePoint, toolMode]); + + useEffect(() => { + if (deletePointOrLine) { + setToolMode(null); + setMovePoint(false); + } + }, [deletePointOrLine]); + + useEffect(() => { + Layer2DVisibility(activeLayer, floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, currentLayerPoint, dragPointControls); + }, [activeLayer]); + + useEffect(() => { + if (removedLayer !== null) { + DeleteLayer(removedLayer, lines, floorPlanGroupLine, floorPlanGroupPoint, onlyFloorlines, floorGroup, setDeletedLines, setRemovedLayer, socket); + } + }, [removedLayer]); + + useEffect(() => { + + const canvasElement = gl.domElement; + + let drag = false; + let isLeftMouseDown = false; + + const onMouseDown = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = true; + drag = false; + } + }; + + const onMouseUp = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = false; + } + if (controls) { + (controls as any).enabled = true; + } + } + + const onMouseMove = () => { + if (isLeftMouseDown) { + drag = true; + } + }; + + const onContextMenu = (e: any) => { + e.preventDefault(); + if (toolMode === "Wall" || toolMode === "Floor") { + removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); + removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); + } + }; + + const onMouseClick = (evt: any) => { + if (!plane.current || drag) return; + + if (deletePointOrLine) { + if (hoveredDeletablePoint.current !== null) { + deletePoint(hoveredDeletablePoint, onlyFloorlines, floorPlanGroupPoint, floorPlanGroupLine, lines, setDeletedLines, socket); + } + if (hoveredDeletableLine.current !== null) { + deleteLine(hoveredDeletableLine, onlyFloorlines, lines, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, socket); + } + } + + if (toolMode === "Wall") { + drawWall(raycaster, plane, floorPlanGroupPoint, snappedPoint, isSnapped, isSnappedUUID, line, ispreSnapped, anglesnappedPoint, isAngleSnapped, lines, floorPlanGroupLine, floorPlanGroup, ReferenceLineMesh, LineCreated, currentLayerPoint, dragPointControls, setNewLines, setDeletedLines, activeLayer, socket); + } + + if (toolMode === "Floor") { + drawOnlyFloor(raycaster, state, camera, plane, floorPlanGroupPoint, snappedPoint, isSnapped, isSnappedUUID, line, ispreSnapped, anglesnappedPoint, isAngleSnapped, onlyFloorline, onlyFloorlines, lines, floorPlanGroupLine, floorPlanGroup, ReferenceLineMesh, LineCreated, currentLayerPoint, dragPointControls, setNewLines, setDeletedLines, activeLayer, socket); + } + } + + if (deletePointOrLine || toolMode === "Wall" || toolMode === "Floor") { + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + canvasElement.addEventListener("click", onMouseClick); + canvasElement.addEventListener("contextmenu", onContextMenu); + } + + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + canvasElement.removeEventListener("click", onMouseClick); + canvasElement.removeEventListener("contextmenu", onContextMenu); + }; + }, [deletePointOrLine, toolMode, activeLayer]) + + + useFrame(() => { + if (deletePointOrLine) { + DeletableLineorPoint(state, plane, floorPlanGroupLine, floorPlanGroupPoint, hoveredDeletableLine, hoveredDeletablePoint); + } + }) + + return ( + + + + + ) +} + export default FloorPlanGroup; \ No newline at end of file diff --git a/app/src/modules/builder/groups/wallItemsGroup.tsx b/app/src/modules/builder/groups/wallItemsGroup.tsx index a8c6211..00d7834 100644 --- a/app/src/modules/builder/groups/wallItemsGroup.tsx +++ b/app/src/modules/builder/groups/wallItemsGroup.tsx @@ -1,289 +1,289 @@ -import { useEffect } from "react"; -import { useDeleteModels, useDeletePointOrLine, useObjectPosition, useObjectRotation, useObjectScale, useSelectedWallItem, useSocketStore, useWallItems } from "../../../store/store"; -import { Csg } from "../csg/csg"; -import * as Types from "../../../types/world/worldTypes"; -import * as CONSTANTS from "../../../types/world/worldConstants"; -import * as THREE from "three"; -import { useThree } from "@react-three/fiber"; -import handleMeshMissed from "../eventFunctions/handleMeshMissed"; -import DeleteWallItems from "../geomentries/walls/deleteWallItems"; -import loadInitialWallItems from "../../scene/IntialLoad/loadInitialWallItems"; -import AddWallItems from "../geomentries/walls/addWallItems"; - - -const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletableWallItem, selectedItemsIndex, setSelectedItemsIndex, CSGGroup }: any) => { - const { deleteModels, setDeleteModels } = useDeleteModels(); - const { wallItems, setWallItems } = useWallItems(); - const { objectPosition, setObjectPosition } = useObjectPosition(); - const { objectScale, setObjectScale } = useObjectScale(); - const { objectRotation, setObjectRotation } = useObjectRotation(); - const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); - const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem(); - const { socket } = useSocketStore(); - const state = useThree(); - const { pointer, camera, raycaster } = state; - - - useEffect(() => { - // Load Wall Items from the backend - loadInitialWallItems(setWallItems, AssetConfigurations); - }, []); - - - ////////// Update the Scale value changes in thewallItems State ////////// - - ////////// Update the Position value changes in the selected item ////////// - - ////////// Update the Rotation value changes in the selected item ////////// - - useEffect(() => { - if (objectScale.x && objectScale.y && objectScale.z) { - let ScaledWallItems: Types.wallItems = []; - wallItems.forEach((items: any) => { - if (items.model?.uuid === currentWallItem.current?.parent?.uuid) { - items.scale = [objectScale.x, objectScale.y, objectScale.z]; - } - ScaledWallItems.push(items); - }); - setWallItems(ScaledWallItems); - } - }, [objectScale]); - - useEffect(() => { - if (objectPosition.x && objectPosition.y && objectPosition.z) { - let ScaledWallItems: Types.wallItems = []; - wallItems.forEach((items: any) => { - if (items.model?.uuid === currentWallItem.current?.parent?.uuid) { - items.position = [objectPosition.x, objectPosition.y, objectPosition.z]; - } - ScaledWallItems.push(items); - }); - setWallItems(ScaledWallItems); - } - }, [objectPosition]); - - useEffect(() => { - if (objectRotation.x && objectRotation.y && objectRotation.z) { - let ScaledWallItems: Types.wallItems = []; - wallItems.forEach((items: any) => { - if (items.model?.uuid === currentWallItem.current?.parent?.uuid) { - const radiansX = objectRotation.x * (Math.PI / 180); - const radiansY = objectRotation.y * (Math.PI / 180); - const radiansZ = objectRotation.z * (Math.PI / 180); - const quaternion = new THREE.Quaternion().setFromEuler( - new THREE.Euler(radiansX, radiansY, radiansZ) - ); - items.quaternion = [quaternion.x, quaternion.y, quaternion.z, quaternion.w]; - } - ScaledWallItems.push(items); - }); - setWallItems(ScaledWallItems); - } - }, [objectRotation]); - - useEffect(() => { - const canvasElement = state.gl.domElement; - function handlePointerMove(e: any) { - if (selectedItemsIndex !== null && !deletePointOrLine && e.buttons === 1) { - const Raycaster = state.raycaster; - const intersects = Raycaster.intersectObjects(CSGGroup.current?.children[0].children!, true); - const Object = intersects.find((child) => child.object.name.includes("WallRaycastReference")); - - if (Object) { - (state.controls as any)!.enabled = false; - setWallItems((prevItems: any) => { - const updatedItems = [...prevItems]; - let position: [number, number, number] = [0, 0, 0]; - - if (updatedItems[selectedItemsIndex].type === "Fixed-Move") { - position = [Object!.point.x, Math.floor(Object!.point.y / CONSTANTS.wallConfig.height) * CONSTANTS.wallConfig.height, Object!.point.z]; - } else if (updatedItems[selectedItemsIndex].type === "Free-Move") { - position = [Object!.point.x, Object!.point.y, Object!.point.z]; - } - - requestAnimationFrame(() => { - setObjectPosition(new THREE.Vector3(...position)); - setObjectRotation({ - x: THREE.MathUtils.radToDeg(Object!.object.rotation.x), - y: THREE.MathUtils.radToDeg(Object!.object.rotation.y), - z: THREE.MathUtils.radToDeg(Object!.object.rotation.z), - }); - }); - - updatedItems[selectedItemsIndex] = { - ...updatedItems[selectedItemsIndex], - position: position, - quaternion: Object!.object.quaternion.clone() as Types.QuaternionType, - }; - - return updatedItems; - }); - } - } - } - - async function handlePointerUp() { - const Raycaster = state.raycaster; - const intersects = Raycaster.intersectObjects(CSGGroup.current?.children[0].children!, true); - const Object = intersects.find((child) => child.object.name.includes("WallRaycastReference")); - if (Object) { - if (selectedItemsIndex !== null) { - let currentItem: any = null; - setWallItems((prevItems: any) => { - const updatedItems = [...prevItems]; - const WallItemsForStorage = updatedItems.map((item) => { - const { model, ...rest } = item; - return { - ...rest, - modeluuid: model?.uuid, - }; - }); - - currentItem = updatedItems[selectedItemsIndex]; - localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); - return updatedItems; - }); - - setTimeout(async () => { - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // await setWallItem( - // organization, - // currentItem?.model?.uuid, - // currentItem.modelname, - // currentItem.type!, - // currentItem.csgposition!, - // currentItem.csgscale!, - // currentItem.position, - // currentItem.quaternion, - // currentItem.scale!, - // ) - - //SOCKET - - const data = { - organization: organization, - modeluuid: currentItem.model?.uuid!, - modelname: currentItem.modelname!, - type: currentItem.type!, - csgposition: currentItem.csgposition!, - csgscale: currentItem.csgscale!, - position: currentItem.position!, - quaternion: currentItem.quaternion, - scale: currentItem.scale!, - socketId: socket.id - } - - socket.emit('v1:wallItems:set', data); - }, 0); - (state.controls as any)!.enabled = true; - } - } - } - - canvasElement.addEventListener("pointermove", handlePointerMove); - canvasElement.addEventListener("pointerup", handlePointerUp); - - return () => { - canvasElement.removeEventListener("pointermove", handlePointerMove); - canvasElement.removeEventListener("pointerup", handlePointerUp); - }; - }, [selectedItemsIndex]); - - useEffect(() => { - const canvasElement = state.gl.domElement; - let drag = false; - let isLeftMouseDown = false; - - const onMouseDown = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = true; - drag = false; - } - }; - - const onMouseUp = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = false; - if (!drag && deleteModels) { - DeleteWallItems(hoveredDeletableWallItem, setWallItems, wallItems, socket); - } - } - }; - - const onMouseMove = () => { - if (isLeftMouseDown) { - drag = true; - } - }; - - const onDrop = (event: any) => { - - if (!event.dataTransfer?.files[0]) return - pointer.x = (event.clientX / window.innerWidth) * 2 - 1; - pointer.y = -(event.clientY / window.innerHeight) * 2 + 1; - raycaster.setFromCamera(pointer, camera); - - if (AssetConfigurations[(event.dataTransfer.files[0].name.split('.'))[0]]) { - const selected = (event.dataTransfer.files[0].name.split('.'))[0]; - - if (AssetConfigurations[selected]?.type) { - AddWallItems(selected, raycaster, CSGGroup, AssetConfigurations, setWallItems, socket); - } - event.preventDefault(); - } - } - - const onDragOver = (event: any) => { - event.preventDefault(); - }; - - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - canvasElement.addEventListener("drop", onDrop); - canvasElement.addEventListener("dragover", onDragOver); - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - canvasElement.removeEventListener("drop", onDrop); - canvasElement.removeEventListener("dragover", onDragOver); - }; - }, [deleteModels, wallItems]) - - useEffect(() => { - if (deleteModels) { - handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex); - setSelectedWallItem(null); - setSelectedItemsIndex(null); - } - }, [deleteModels]) - - return ( - <> - {wallItems.map((item: Types.WallItem, index: number) => ( - - - - ))} - - ) -} - +import { useEffect } from "react"; +import { useDeleteModels, useDeletePointOrLine, useObjectPosition, useObjectRotation, useObjectScale, useSelectedWallItem, useSocketStore, useWallItems } from "../../../store/store"; +import { Csg } from "../csg/csg"; +import * as Types from "../../../types/world/worldTypes"; +import * as CONSTANTS from "../../../types/world/worldConstants"; +import * as THREE from "three"; +import { useThree } from "@react-three/fiber"; +import handleMeshMissed from "../eventFunctions/handleMeshMissed"; +import DeleteWallItems from "../geomentries/walls/deleteWallItems"; +import loadInitialWallItems from "../../scene/IntialLoad/loadInitialWallItems"; +import AddWallItems from "../geomentries/walls/addWallItems"; + + +const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletableWallItem, selectedItemsIndex, setSelectedItemsIndex, CSGGroup }: any) => { + const { deleteModels, setDeleteModels } = useDeleteModels(); + const { wallItems, setWallItems } = useWallItems(); + const { objectPosition, setObjectPosition } = useObjectPosition(); + const { objectScale, setObjectScale } = useObjectScale(); + const { objectRotation, setObjectRotation } = useObjectRotation(); + const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); + const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem(); + const { socket } = useSocketStore(); + const state = useThree(); + const { pointer, camera, raycaster } = state; + + + useEffect(() => { + // Load Wall Items from the backend + loadInitialWallItems(setWallItems, AssetConfigurations); + }, []); + + + ////////// Update the Scale value changes in thewallItems State ////////// + + ////////// Update the Position value changes in the selected item ////////// + + ////////// Update the Rotation value changes in the selected item ////////// + + useEffect(() => { + if (objectScale.x && objectScale.y && objectScale.z) { + let ScaledWallItems: Types.wallItems = []; + wallItems.forEach((items: any) => { + if (items.model?.uuid === currentWallItem.current?.parent?.uuid) { + items.scale = [objectScale.x, objectScale.y, objectScale.z]; + } + ScaledWallItems.push(items); + }); + setWallItems(ScaledWallItems); + } + }, [objectScale]); + + useEffect(() => { + if (objectPosition.x && objectPosition.y && objectPosition.z) { + let ScaledWallItems: Types.wallItems = []; + wallItems.forEach((items: any) => { + if (items.model?.uuid === currentWallItem.current?.parent?.uuid) { + items.position = [objectPosition.x, objectPosition.y, objectPosition.z]; + } + ScaledWallItems.push(items); + }); + setWallItems(ScaledWallItems); + } + }, [objectPosition]); + + useEffect(() => { + if (objectRotation.x && objectRotation.y && objectRotation.z) { + let ScaledWallItems: Types.wallItems = []; + wallItems.forEach((items: any) => { + if (items.model?.uuid === currentWallItem.current?.parent?.uuid) { + const radiansX = objectRotation.x * (Math.PI / 180); + const radiansY = objectRotation.y * (Math.PI / 180); + const radiansZ = objectRotation.z * (Math.PI / 180); + const quaternion = new THREE.Quaternion().setFromEuler( + new THREE.Euler(radiansX, radiansY, radiansZ) + ); + items.quaternion = [quaternion.x, quaternion.y, quaternion.z, quaternion.w]; + } + ScaledWallItems.push(items); + }); + setWallItems(ScaledWallItems); + } + }, [objectRotation]); + + useEffect(() => { + const canvasElement = state.gl.domElement; + function handlePointerMove(e: any) { + if (selectedItemsIndex !== null && !deletePointOrLine && e.buttons === 1) { + const Raycaster = state.raycaster; + const intersects = Raycaster.intersectObjects(CSGGroup.current?.children[0].children!, true); + const Object = intersects.find((child) => child.object.name.includes("WallRaycastReference")); + + if (Object) { + (state.controls as any)!.enabled = false; + setWallItems((prevItems: any) => { + const updatedItems = [...prevItems]; + let position: [number, number, number] = [0, 0, 0]; + + if (updatedItems[selectedItemsIndex].type === "Fixed-Move") { + position = [Object!.point.x, Math.floor(Object!.point.y / CONSTANTS.wallConfig.height) * CONSTANTS.wallConfig.height, Object!.point.z]; + } else if (updatedItems[selectedItemsIndex].type === "Free-Move") { + position = [Object!.point.x, Object!.point.y, Object!.point.z]; + } + + requestAnimationFrame(() => { + setObjectPosition(new THREE.Vector3(...position)); + setObjectRotation({ + x: THREE.MathUtils.radToDeg(Object!.object.rotation.x), + y: THREE.MathUtils.radToDeg(Object!.object.rotation.y), + z: THREE.MathUtils.radToDeg(Object!.object.rotation.z), + }); + }); + + updatedItems[selectedItemsIndex] = { + ...updatedItems[selectedItemsIndex], + position: position, + quaternion: Object!.object.quaternion.clone() as Types.QuaternionType, + }; + + return updatedItems; + }); + } + } + } + + async function handlePointerUp() { + const Raycaster = state.raycaster; + const intersects = Raycaster.intersectObjects(CSGGroup.current?.children[0].children!, true); + const Object = intersects.find((child) => child.object.name.includes("WallRaycastReference")); + if (Object) { + if (selectedItemsIndex !== null) { + let currentItem: any = null; + setWallItems((prevItems: any) => { + const updatedItems = [...prevItems]; + const WallItemsForStorage = updatedItems.map((item) => { + const { model, ...rest } = item; + return { + ...rest, + modeluuid: model?.uuid, + }; + }); + + currentItem = updatedItems[selectedItemsIndex]; + localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); + return updatedItems; + }); + + setTimeout(async () => { + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // await setWallItem( + // organization, + // currentItem?.model?.uuid, + // currentItem.modelname, + // currentItem.type!, + // currentItem.csgposition!, + // currentItem.csgscale!, + // currentItem.position, + // currentItem.quaternion, + // currentItem.scale!, + // ) + + //SOCKET + + const data = { + organization: organization, + modeluuid: currentItem.model?.uuid!, + modelname: currentItem.modelname!, + type: currentItem.type!, + csgposition: currentItem.csgposition!, + csgscale: currentItem.csgscale!, + position: currentItem.position!, + quaternion: currentItem.quaternion, + scale: currentItem.scale!, + socketId: socket.id + } + + socket.emit('v1:wallItems:set', data); + }, 0); + (state.controls as any)!.enabled = true; + } + } + } + + canvasElement.addEventListener("pointermove", handlePointerMove); + canvasElement.addEventListener("pointerup", handlePointerUp); + + return () => { + canvasElement.removeEventListener("pointermove", handlePointerMove); + canvasElement.removeEventListener("pointerup", handlePointerUp); + }; + }, [selectedItemsIndex]); + + useEffect(() => { + const canvasElement = state.gl.domElement; + let drag = false; + let isLeftMouseDown = false; + + const onMouseDown = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = true; + drag = false; + } + }; + + const onMouseUp = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = false; + if (!drag && deleteModels) { + DeleteWallItems(hoveredDeletableWallItem, setWallItems, wallItems, socket); + } + } + }; + + const onMouseMove = () => { + if (isLeftMouseDown) { + drag = true; + } + }; + + const onDrop = (event: any) => { + + if (!event.dataTransfer?.files[0]) return + pointer.x = (event.clientX / window.innerWidth) * 2 - 1; + pointer.y = -(event.clientY / window.innerHeight) * 2 + 1; + raycaster.setFromCamera(pointer, camera); + + if (AssetConfigurations[(event.dataTransfer.files[0].name.split('.'))[0]]) { + const selected = (event.dataTransfer.files[0].name.split('.'))[0]; + + if (AssetConfigurations[selected]?.type) { + AddWallItems(selected, raycaster, CSGGroup, AssetConfigurations, setWallItems, socket); + } + event.preventDefault(); + } + } + + const onDragOver = (event: any) => { + event.preventDefault(); + }; + + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + canvasElement.addEventListener("drop", onDrop); + canvasElement.addEventListener("dragover", onDragOver); + + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + canvasElement.removeEventListener("drop", onDrop); + canvasElement.removeEventListener("dragover", onDragOver); + }; + }, [deleteModels, wallItems]) + + useEffect(() => { + if (deleteModels) { + handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex); + setSelectedWallItem(null); + setSelectedItemsIndex(null); + } + }, [deleteModels]) + + return ( + <> + {wallItems.map((item: Types.WallItem, index: number) => ( + + + + ))} + + ) +} + export default WallItemsGroup; \ No newline at end of file diff --git a/app/src/modules/builder/groups/wallsAndWallItems.tsx b/app/src/modules/builder/groups/wallsAndWallItems.tsx index a4e7d71..7366f28 100644 --- a/app/src/modules/builder/groups/wallsAndWallItems.tsx +++ b/app/src/modules/builder/groups/wallsAndWallItems.tsx @@ -1,56 +1,56 @@ -import { Geometry } from "@react-three/csg"; -import { useDeleteModels, useSelectedWallItem, useToggleView, useTransformMode, useWallItems, useWalls } from "../../../store/store"; -import handleMeshDown from "../eventFunctions/handleMeshDown"; -import handleMeshMissed from "../eventFunctions/handleMeshMissed"; -import WallsMesh from "./wallsMesh"; -import WallItemsGroup from "./wallItemsGroup"; -import { useEffect } from "react"; - - -const WallsAndWallItems = ({ CSGGroup, AssetConfigurations, setSelectedItemsIndex, selectedItemsIndex, currentWallItem, csg, lines, hoveredDeletableWallItem }: any) => { - const { walls, setWalls } = useWalls(); - const { wallItems, setWallItems } = useWallItems(); - const { toggleView, setToggleView } = useToggleView(); - const { deleteModels, setDeleteModels } = useDeleteModels(); - const { transformMode, setTransformMode } = useTransformMode(); - const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem(); - - useEffect(() => { - if (transformMode === null) { - if (!deleteModels) { - handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex); - setSelectedWallItem(null); - setSelectedItemsIndex(null); - } - } - }, [transformMode]) - - return ( - { - if (!deleteModels && transformMode !== null) { - handleMeshDown(event, currentWallItem, setSelectedWallItem, setSelectedItemsIndex, wallItems, toggleView); - } - }} - onPointerMissed={() => { - if (!deleteModels) { - handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex); - setSelectedWallItem(null); - setSelectedItemsIndex(null); - } - }} - > - - - - - - ) -} - +import { Geometry } from "@react-three/csg"; +import { useDeleteModels, useSelectedWallItem, useToggleView, useTransformMode, useWallItems, useWalls } from "../../../store/store"; +import handleMeshDown from "../eventFunctions/handleMeshDown"; +import handleMeshMissed from "../eventFunctions/handleMeshMissed"; +import WallsMesh from "./wallsMesh"; +import WallItemsGroup from "./wallItemsGroup"; +import { useEffect } from "react"; + + +const WallsAndWallItems = ({ CSGGroup, AssetConfigurations, setSelectedItemsIndex, selectedItemsIndex, currentWallItem, csg, lines, hoveredDeletableWallItem }: any) => { + const { walls, setWalls } = useWalls(); + const { wallItems, setWallItems } = useWallItems(); + const { toggleView, setToggleView } = useToggleView(); + const { deleteModels, setDeleteModels } = useDeleteModels(); + const { transformMode, setTransformMode } = useTransformMode(); + const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem(); + + useEffect(() => { + if (transformMode === null) { + if (!deleteModels) { + handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex); + setSelectedWallItem(null); + setSelectedItemsIndex(null); + } + } + }, [transformMode]) + + return ( + { + if (!deleteModels && transformMode !== null) { + handleMeshDown(event, currentWallItem, setSelectedWallItem, setSelectedItemsIndex, wallItems, toggleView); + } + }} + onPointerMissed={() => { + if (!deleteModels) { + handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex); + setSelectedWallItem(null); + setSelectedItemsIndex(null); + } + }} + > + + + + + + ) +} + export default WallsAndWallItems; \ No newline at end of file diff --git a/app/src/modules/builder/groups/wallsMesh.tsx b/app/src/modules/builder/groups/wallsMesh.tsx index a82bbb4..92a0ee3 100644 --- a/app/src/modules/builder/groups/wallsMesh.tsx +++ b/app/src/modules/builder/groups/wallsMesh.tsx @@ -1,65 +1,65 @@ -import * as THREE from 'three'; -import * as Types from '../../../types/world/worldTypes'; -import * as CONSTANTS from '../../../types/world/worldConstants'; -import { Base } from '@react-three/csg'; -import { MeshDiscardMaterial } from '@react-three/drei'; -import { useUpdateScene, useWalls } from '../../../store/store'; -import { useEffect } from 'react'; -import { getLines } from '../../../services/factoryBuilder/lines/getLinesApi'; -import objectLinesToArray from '../geomentries/lines/lineConvertions/objectLinesToArray'; -import loadWalls from '../geomentries/walls/loadWalls'; - -const WallsMesh = ({ lines }: any) => { - const { walls, setWalls } = useWalls(); - const { updateScene, setUpdateScene } = useUpdateScene(); - - useEffect(() => { - if (updateScene) { - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - getLines(organization).then((data) => { - const Lines: Types.Lines = objectLinesToArray(data); - localStorage.setItem("Lines", JSON.stringify(Lines)); - - if (Lines) { - loadWalls(lines, setWalls); - } - }) - setUpdateScene(false); - } - }, [updateScene]) - - return ( - <> - {walls.map((wall: Types.Wall, index: number) => ( - - - - - - - - - ))} - - ) -} - +import * as THREE from 'three'; +import * as Types from '../../../types/world/worldTypes'; +import * as CONSTANTS from '../../../types/world/worldConstants'; +import { Base } from '@react-three/csg'; +import { MeshDiscardMaterial } from '@react-three/drei'; +import { useUpdateScene, useWalls } from '../../../store/store'; +import { useEffect } from 'react'; +import { getLines } from '../../../services/factoryBuilder/lines/getLinesApi'; +import objectLinesToArray from '../geomentries/lines/lineConvertions/objectLinesToArray'; +import loadWalls from '../geomentries/walls/loadWalls'; + +const WallsMesh = ({ lines }: any) => { + const { walls, setWalls } = useWalls(); + const { updateScene, setUpdateScene } = useUpdateScene(); + + useEffect(() => { + if (updateScene) { + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + getLines(organization).then((data) => { + const Lines: Types.Lines = objectLinesToArray(data); + localStorage.setItem("Lines", JSON.stringify(Lines)); + + if (Lines) { + loadWalls(lines, setWalls); + } + }) + setUpdateScene(false); + } + }, [updateScene]) + + return ( + <> + {walls.map((wall: Types.Wall, index: number) => ( + + + + + + + + + ))} + + ) +} + export default WallsMesh; \ No newline at end of file diff --git a/app/src/modules/builder/groups/zoneGroup.tsx b/app/src/modules/builder/groups/zoneGroup.tsx index bd0087e..4676a1d 100644 --- a/app/src/modules/builder/groups/zoneGroup.tsx +++ b/app/src/modules/builder/groups/zoneGroup.tsx @@ -1,466 +1,466 @@ -import React, { useState, useEffect, useMemo, useRef } from "react"; -import { Line, Sphere } from "@react-three/drei"; -import { useThree, useFrame } from "@react-three/fiber"; -import * as THREE from "three"; -import { useActiveLayer, useDeleteModels, useDeletePointOrLine, useMovePoint, useSocketStore, useToggleView, useToolMode, useRemovedLayer, useZones, useZonePoints } from "../../../store/store"; -// import { setZonesApi } from "../../../services/factoryBuilder/zones/setZonesApi"; -// import { deleteZonesApi } from "../../../services/factoryBuilder/zones/deleteZoneApi"; -import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi"; - -import * as CONSTANTS from '../../../types/world/worldConstants'; - -const ZoneGroup: React.FC = () => { - const { camera, pointer, gl, raycaster, scene, controls } = useThree(); - const [startPoint, setStartPoint] = useState(null); - const [endPoint, setEndPoint] = useState(null); - const { zones, setZones } = useZones(); - const { zonePoints, setZonePoints } = useZonePoints(); - const [isDragging, setIsDragging] = useState(false); - const [draggedSphere, setDraggedSphere] = useState(null); - const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); - const { toggleView } = useToggleView(); - const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); - const { removedLayer, setRemovedLayer } = useRemovedLayer(); - const { toolMode, setToolMode } = useToolMode(); - const { movePoint, setMovePoint } = useMovePoint(); - const { deleteModels, setDeleteModels } = useDeleteModels(); - const { activeLayer, setActiveLayer } = useActiveLayer(); - const { socket } = useSocketStore(); - - const groupsRef = useRef(); - - const zoneMaterial = useMemo(() => new THREE.ShaderMaterial({ - side: THREE.DoubleSide, - vertexShader: ` - varying vec2 vUv; - void main(){ - gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); - vUv = uv; - } - `, - fragmentShader: ` - varying vec2 vUv; - uniform vec3 uColor; - void main(){ - float alpha = 1.0 - vUv.y; - gl_FragColor = vec4(uColor, alpha); - } - `, - uniforms: { - uColor: { value: new THREE.Color(CONSTANTS.zoneConfig.color) }, - }, - transparent: true, - }), []); - - useEffect(() => { - const fetchZones = async () => { - const email = localStorage.getItem('email'); - if (!email) return; - - const organization = email.split("@")[1].split(".")[0]; - const data = await getZonesApi(organization); - - if (data.data && data.data.length > 0) { - const fetchedZones = data.data.map((zone: any) => ({ - zoneId: zone.zoneId, - zoneName: zone.zoneName, - points: zone.points, - layer: zone.layer - })); - - setZones(fetchedZones); - - const fetchedPoints = data.data.flatMap((zone: any) => - zone.points.slice(0, 4).map((point: [number, number, number]) => new THREE.Vector3(...point)) - ); - - setZonePoints(fetchedPoints); - } - }; - - fetchZones(); - }, []); - - useEffect(() => { - - localStorage.setItem('zones', zones); - - }, [zones]) - - useEffect(() => { - if (removedLayer) { - const updatedZones = zones.filter((zone: any) => zone.layer !== removedLayer); - setZones(updatedZones); - - const updatedzonePoints = zonePoints.filter((_: any, index: any) => { - const zoneIndex = Math.floor(index / 4); - return zones[zoneIndex]?.layer !== removedLayer; - }); - setZonePoints(updatedzonePoints); - - zones.filter((zone: any) => zone.layer === removedLayer).forEach((zone: any) => { - deleteZoneFromBackend(zone.zoneId); - }); - - setRemovedLayer(null); - } - }, [removedLayer]); - - useEffect(() => { - if (toolMode !== "Zone") { - setStartPoint(null); - setEndPoint(null); - } else { - setDeletePointOrLine(false); - setMovePoint(false); - setDeleteModels(false); - } - if (!toggleView) { - setStartPoint(null); - setEndPoint(null); - } - }, [toolMode, toggleView]); - - - const addZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => { - - const email = localStorage.getItem('email'); - const userId = localStorage.getItem('userId'); - const organization = (email!.split("@")[1]).split(".")[0]; - - const input = { - userId: userId, - organization: organization, - zoneData: { - zoneName: zone.zoneName, - zoneId: zone.zoneId, - points: zone.points, - layer: zone.layer - } - } - - socket.emit('v2:zone:set', input); - }; - - const updateZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => { - - const email = localStorage.getItem('email'); - const userId = localStorage.getItem('userId'); - const organization = (email!.split("@")[1]).split(".")[0]; - - const input = { - userId: userId, - organization: organization, - zoneData: { - zoneName: zone.zoneName, - zoneId: zone.zoneId, - points: zone.points, - layer: zone.layer - } - } - - socket.emit('v2:zone:set', input); - }; - - const deleteZoneFromBackend = async (zoneId: string) => { - - const email = localStorage.getItem('email'); - const userId = localStorage.getItem('userId'); - const organization = (email!.split("@")[1]).split(".")[0]; - - const input = { - userId: userId, - organization: organization, - zoneId: zoneId - } - - socket.emit('v2:zone:delete', input); - }; - - const handleDeleteZone = (zoneId: string) => { - const updatedZones = zones.filter((zone: any) => zone.zoneId !== zoneId); - setZones(updatedZones); - - const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === zoneId); - if (zoneIndex !== -1) { - const zonePointsToRemove = zonePoints.slice(zoneIndex * 4, zoneIndex * 4 + 4); - zonePointsToRemove.forEach((point: any) => groupsRef.current.remove(point)); - const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4); - setZonePoints(updatedzonePoints); - } - - deleteZoneFromBackend(zoneId); - }; - - useEffect(() => { - if (!camera || !toggleView) return; - const canvasElement = gl.domElement; - - let drag = false; - let isLeftMouseDown = false; - - const onMouseDown = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = true; - drag = false; - - raycaster.setFromCamera(pointer, camera); - const intersects = raycaster.intersectObjects(groupsRef.current.children, true); - - if (intersects.length > 0 && movePoint) { - const clickedObject = intersects[0].object; - const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position)); - if (sphereIndex !== -1) { - (controls as any).enabled = false; - setDraggedSphere(zonePoints[sphereIndex]); - setIsDragging(true); - } - } - } - }; - - const onMouseUp = (evt: any) => { - if (evt.button === 0 && !drag && !isDragging && !deletePointOrLine) { - isLeftMouseDown = false; - - if (!startPoint && !movePoint) { - raycaster.setFromCamera(pointer, camera); - const intersectionPoint = new THREE.Vector3(); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - if (point) { - setStartPoint(point); - setEndPoint(null); - } - } else if (startPoint && !movePoint) { - raycaster.setFromCamera(pointer, camera); - const intersectionPoint = new THREE.Vector3(); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - if (!point) return; - - const points = [ - [startPoint.x, 0.15, startPoint.z], - [point.x, 0.15, startPoint.z], - [point.x, 0.15, point.z], - [startPoint.x, 0.15, point.z], - [startPoint.x, 0.15, startPoint.z], - ] as [number, number, number][]; - - const zoneName = `Zone ${zones.length + 1}`; - const zoneId = THREE.MathUtils.generateUUID(); - const newZone = { - zoneId, - zoneName, - points: points, - layer: activeLayer - }; - - const newZones = [...zones, newZone]; - - setZones(newZones); - - const newzonePoints = [ - new THREE.Vector3(startPoint.x, 0.15, startPoint.z), - new THREE.Vector3(point.x, 0.15, startPoint.z), - new THREE.Vector3(point.x, 0.15, point.z), - new THREE.Vector3(startPoint.x, 0.15, point.z), - ]; - - const updatedZonePoints = [...zonePoints, ...newzonePoints]; - setZonePoints(updatedZonePoints); - - addZoneToBackend(newZone); - - setStartPoint(null); - setEndPoint(null); - } - } else if (evt.button === 0 && !drag && !isDragging && deletePointOrLine) { - raycaster.setFromCamera(pointer, camera); - const intersects = raycaster.intersectObjects(groupsRef.current.children, true); - - if (intersects.length > 0) { - const clickedObject = intersects[0].object; - - const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position)); - if (sphereIndex !== -1) { - const zoneIndex = Math.floor(sphereIndex / 4); - const zoneId = zones[zoneIndex].zoneId; - handleDeleteZone(zoneId); - return; - } - } - } - - if (evt.button === 0) { - if (isDragging && draggedSphere) { - setIsDragging(false); - setDraggedSphere(null); - - const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere); - if (sphereIndex !== -1) { - const zoneIndex = Math.floor(sphereIndex / 4); - - if (zoneIndex !== -1 && zones[zoneIndex]) { - updateZoneToBackend(zones[zoneIndex]); - } - } - } - } - }; - - const onMouseMove = () => { - if (isLeftMouseDown) { - drag = true; - } - raycaster.setFromCamera(pointer, camera); - const intersects = raycaster.intersectObjects(groupsRef.current.children, true); - - if (intersects.length > 0 && intersects[0].object.name.includes('point')) { - gl.domElement.style.cursor = movePoint ? "pointer" : "default"; - } else { - gl.domElement.style.cursor = "default"; - } - if (isDragging && draggedSphere) { - raycaster.setFromCamera(pointer, camera); - const intersectionPoint = new THREE.Vector3(); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - if (point) { - draggedSphere.set(point.x, 0.15, point.z); - - const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere); - if (sphereIndex !== -1) { - const zoneIndex = Math.floor(sphereIndex / 4); - const cornerIndex = sphereIndex % 4; - - const updatedZones = zones.map((zone: any, index: number) => { - if (index === zoneIndex) { - const updatedPoints = [...zone.points]; - updatedPoints[cornerIndex] = [point.x, 0.15, point.z]; - updatedPoints[4] = updatedPoints[0]; - return { ...zone, points: updatedPoints }; - } - return zone; - }); - - setZones(updatedZones); - } - } - } - }; - - const onContext = (event: any) => { - event.preventDefault(); - setStartPoint(null); - setEndPoint(null); - }; - - if (toolMode === 'Zone' || deletePointOrLine || movePoint) { - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - canvasElement.addEventListener("contextmenu", onContext); - } - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - canvasElement.removeEventListener("contextmenu", onContext); - }; - }, [gl, camera, startPoint, toggleView, scene, toolMode, zones, isDragging, deletePointOrLine, zonePoints, draggedSphere, movePoint, activeLayer]); - - useFrame(() => { - if (!startPoint) return; - raycaster.setFromCamera(pointer, camera); - const intersectionPoint = new THREE.Vector3(); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - if (point) { - setEndPoint(point); - } - }); - return ( - - - {zones - .map((zone: any) => ( - - {zone.points.slice(0, -1).map((point: [number, number, number], index: number) => { - const nextPoint = zone.points[index + 1]; - - const point1 = new THREE.Vector3(point[0], point[1], point[2]); - const point2 = new THREE.Vector3(nextPoint[0], nextPoint[1], nextPoint[2]); - - const planeWidth = point1.distanceTo(point2); - const planeHeight = CONSTANTS.wallConfig.height; - - const midpoint = new THREE.Vector3((point1.x + point2.x) / 2, (CONSTANTS.wallConfig.height / 2) + ((zone.layer - 1) * CONSTANTS.wallConfig.height), (point1.z + point2.z) / 2); - - const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x); - - return ( - - - - - ); - })} - - ))} - - - {zones - .filter((zone: any) => zone.layer === activeLayer) - .map((zone: any) => ( - { - e.stopPropagation(); - if (deletePointOrLine) { - handleDeleteZone(zone.zoneId); - } - }} - /> - ))} - - - {zones.filter((zone: any) => zone.layer === activeLayer).flatMap((zone: any) => ( - zone.points.slice(0, 4).map((point: any, pointIndex: number) => ( - - - - )) - ))} - - - {startPoint && endPoint && ( - - )} - - - ); -}; - +import React, { useState, useEffect, useMemo, useRef } from "react"; +import { Line, Sphere } from "@react-three/drei"; +import { useThree, useFrame } from "@react-three/fiber"; +import * as THREE from "three"; +import { useActiveLayer, useDeleteModels, useDeletePointOrLine, useMovePoint, useSocketStore, useToggleView, useToolMode, useRemovedLayer, useZones, useZonePoints } from "../../../store/store"; +// import { setZonesApi } from "../../../services/factoryBuilder/zones/setZonesApi"; +// import { deleteZonesApi } from "../../../services/factoryBuilder/zones/deleteZoneApi"; +import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi"; + +import * as CONSTANTS from '../../../types/world/worldConstants'; + +const ZoneGroup: React.FC = () => { + const { camera, pointer, gl, raycaster, scene, controls } = useThree(); + const [startPoint, setStartPoint] = useState(null); + const [endPoint, setEndPoint] = useState(null); + const { zones, setZones } = useZones(); + const { zonePoints, setZonePoints } = useZonePoints(); + const [isDragging, setIsDragging] = useState(false); + const [draggedSphere, setDraggedSphere] = useState(null); + const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); + const { toggleView } = useToggleView(); + const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); + const { removedLayer, setRemovedLayer } = useRemovedLayer(); + const { toolMode, setToolMode } = useToolMode(); + const { movePoint, setMovePoint } = useMovePoint(); + const { deleteModels, setDeleteModels } = useDeleteModels(); + const { activeLayer, setActiveLayer } = useActiveLayer(); + const { socket } = useSocketStore(); + + const groupsRef = useRef(); + + const zoneMaterial = useMemo(() => new THREE.ShaderMaterial({ + side: THREE.DoubleSide, + vertexShader: ` + varying vec2 vUv; + void main(){ + gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); + vUv = uv; + } + `, + fragmentShader: ` + varying vec2 vUv; + uniform vec3 uColor; + void main(){ + float alpha = 1.0 - vUv.y; + gl_FragColor = vec4(uColor, alpha); + } + `, + uniforms: { + uColor: { value: new THREE.Color(CONSTANTS.zoneConfig.color) }, + }, + transparent: true, + }), []); + + useEffect(() => { + const fetchZones = async () => { + const email = localStorage.getItem('email'); + if (!email) return; + + const organization = email.split("@")[1].split(".")[0]; + const data = await getZonesApi(organization); + + if (data.data && data.data.length > 0) { + const fetchedZones = data.data.map((zone: any) => ({ + zoneId: zone.zoneId, + zoneName: zone.zoneName, + points: zone.points, + layer: zone.layer + })); + + setZones(fetchedZones); + + const fetchedPoints = data.data.flatMap((zone: any) => + zone.points.slice(0, 4).map((point: [number, number, number]) => new THREE.Vector3(...point)) + ); + + setZonePoints(fetchedPoints); + } + }; + + fetchZones(); + }, []); + + useEffect(() => { + + localStorage.setItem('zones', JSON.stringify(zones)); + + }, [zones]) + + useEffect(() => { + if (removedLayer) { + const updatedZones = zones.filter((zone: any) => zone.layer !== removedLayer); + setZones(updatedZones); + + const updatedzonePoints = zonePoints.filter((_: any, index: any) => { + const zoneIndex = Math.floor(index / 4); + return zones[zoneIndex]?.layer !== removedLayer; + }); + setZonePoints(updatedzonePoints); + + zones.filter((zone: any) => zone.layer === removedLayer).forEach((zone: any) => { + deleteZoneFromBackend(zone.zoneId); + }); + + setRemovedLayer(null); + } + }, [removedLayer]); + + useEffect(() => { + if (toolMode !== "Zone") { + setStartPoint(null); + setEndPoint(null); + } else { + setDeletePointOrLine(false); + setMovePoint(false); + setDeleteModels(false); + } + if (!toggleView) { + setStartPoint(null); + setEndPoint(null); + } + }, [toolMode, toggleView]); + + + const addZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => { + + const email = localStorage.getItem('email'); + const userId = localStorage.getItem('userId'); + const organization = (email!.split("@")[1]).split(".")[0]; + + const input = { + userId: userId, + organization: organization, + zoneData: { + zoneName: zone.zoneName, + zoneId: zone.zoneId, + points: zone.points, + layer: zone.layer + } + } + + socket.emit('v2:zone:set', input); + }; + + const updateZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => { + + const email = localStorage.getItem('email'); + const userId = localStorage.getItem('userId'); + const organization = (email!.split("@")[1]).split(".")[0]; + + const input = { + userId: userId, + organization: organization, + zoneData: { + zoneName: zone.zoneName, + zoneId: zone.zoneId, + points: zone.points, + layer: zone.layer + } + } + + socket.emit('v2:zone:set', input); + }; + + const deleteZoneFromBackend = async (zoneId: string) => { + + const email = localStorage.getItem('email'); + const userId = localStorage.getItem('userId'); + const organization = (email!.split("@")[1]).split(".")[0]; + + const input = { + userId: userId, + organization: organization, + zoneId: zoneId + } + + socket.emit('v2:zone:delete', input); + }; + + const handleDeleteZone = (zoneId: string) => { + const updatedZones = zones.filter((zone: any) => zone.zoneId !== zoneId); + setZones(updatedZones); + + const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === zoneId); + if (zoneIndex !== -1) { + const zonePointsToRemove = zonePoints.slice(zoneIndex * 4, zoneIndex * 4 + 4); + zonePointsToRemove.forEach((point: any) => groupsRef.current.remove(point)); + const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4); + setZonePoints(updatedzonePoints); + } + + deleteZoneFromBackend(zoneId); + }; + + useEffect(() => { + if (!camera || !toggleView) return; + const canvasElement = gl.domElement; + + let drag = false; + let isLeftMouseDown = false; + + const onMouseDown = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = true; + drag = false; + + raycaster.setFromCamera(pointer, camera); + const intersects = raycaster.intersectObjects(groupsRef.current.children, true); + + if (intersects.length > 0 && movePoint) { + const clickedObject = intersects[0].object; + const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position)); + if (sphereIndex !== -1) { + (controls as any).enabled = false; + setDraggedSphere(zonePoints[sphereIndex]); + setIsDragging(true); + } + } + } + }; + + const onMouseUp = (evt: any) => { + if (evt.button === 0 && !drag && !isDragging && !deletePointOrLine) { + isLeftMouseDown = false; + + if (!startPoint && !movePoint) { + raycaster.setFromCamera(pointer, camera); + const intersectionPoint = new THREE.Vector3(); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + if (point) { + setStartPoint(point); + setEndPoint(null); + } + } else if (startPoint && !movePoint) { + raycaster.setFromCamera(pointer, camera); + const intersectionPoint = new THREE.Vector3(); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + if (!point) return; + + const points = [ + [startPoint.x, 0.15, startPoint.z], + [point.x, 0.15, startPoint.z], + [point.x, 0.15, point.z], + [startPoint.x, 0.15, point.z], + [startPoint.x, 0.15, startPoint.z], + ] as [number, number, number][]; + + const zoneName = `Zone ${zones.length + 1}`; + const zoneId = THREE.MathUtils.generateUUID(); + const newZone = { + zoneId, + zoneName, + points: points, + layer: activeLayer + }; + + const newZones = [...zones, newZone]; + + setZones(newZones); + + const newzonePoints = [ + new THREE.Vector3(startPoint.x, 0.15, startPoint.z), + new THREE.Vector3(point.x, 0.15, startPoint.z), + new THREE.Vector3(point.x, 0.15, point.z), + new THREE.Vector3(startPoint.x, 0.15, point.z), + ]; + + const updatedZonePoints = [...zonePoints, ...newzonePoints]; + setZonePoints(updatedZonePoints); + + addZoneToBackend(newZone); + + setStartPoint(null); + setEndPoint(null); + } + } else if (evt.button === 0 && !drag && !isDragging && deletePointOrLine) { + raycaster.setFromCamera(pointer, camera); + const intersects = raycaster.intersectObjects(groupsRef.current.children, true); + + if (intersects.length > 0) { + const clickedObject = intersects[0].object; + + const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position)); + if (sphereIndex !== -1) { + const zoneIndex = Math.floor(sphereIndex / 4); + const zoneId = zones[zoneIndex].zoneId; + handleDeleteZone(zoneId); + return; + } + } + } + + if (evt.button === 0) { + if (isDragging && draggedSphere) { + setIsDragging(false); + setDraggedSphere(null); + + const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere); + if (sphereIndex !== -1) { + const zoneIndex = Math.floor(sphereIndex / 4); + + if (zoneIndex !== -1 && zones[zoneIndex]) { + updateZoneToBackend(zones[zoneIndex]); + } + } + } + } + }; + + const onMouseMove = () => { + if (isLeftMouseDown) { + drag = true; + } + raycaster.setFromCamera(pointer, camera); + const intersects = raycaster.intersectObjects(groupsRef.current.children, true); + + if (intersects.length > 0 && intersects[0].object.name.includes('point')) { + gl.domElement.style.cursor = movePoint ? "pointer" : "default"; + } else { + gl.domElement.style.cursor = "default"; + } + if (isDragging && draggedSphere) { + raycaster.setFromCamera(pointer, camera); + const intersectionPoint = new THREE.Vector3(); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + if (point) { + draggedSphere.set(point.x, 0.15, point.z); + + const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere); + if (sphereIndex !== -1) { + const zoneIndex = Math.floor(sphereIndex / 4); + const cornerIndex = sphereIndex % 4; + + const updatedZones = zones.map((zone: any, index: number) => { + if (index === zoneIndex) { + const updatedPoints = [...zone.points]; + updatedPoints[cornerIndex] = [point.x, 0.15, point.z]; + updatedPoints[4] = updatedPoints[0]; + return { ...zone, points: updatedPoints }; + } + return zone; + }); + + setZones(updatedZones); + } + } + } + }; + + const onContext = (event: any) => { + event.preventDefault(); + setStartPoint(null); + setEndPoint(null); + }; + + if (toolMode === 'Zone' || deletePointOrLine || movePoint) { + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + canvasElement.addEventListener("contextmenu", onContext); + } + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + canvasElement.removeEventListener("contextmenu", onContext); + }; + }, [gl, camera, startPoint, toggleView, scene, toolMode, zones, isDragging, deletePointOrLine, zonePoints, draggedSphere, movePoint, activeLayer]); + + useFrame(() => { + if (!startPoint) return; + raycaster.setFromCamera(pointer, camera); + const intersectionPoint = new THREE.Vector3(); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + if (point) { + setEndPoint(point); + } + }); + return ( + + + {zones + .map((zone: any) => ( + + {zone.points.slice(0, -1).map((point: [number, number, number], index: number) => { + const nextPoint = zone.points[index + 1]; + + const point1 = new THREE.Vector3(point[0], point[1], point[2]); + const point2 = new THREE.Vector3(nextPoint[0], nextPoint[1], nextPoint[2]); + + const planeWidth = point1.distanceTo(point2); + const planeHeight = CONSTANTS.wallConfig.height; + + const midpoint = new THREE.Vector3((point1.x + point2.x) / 2, (CONSTANTS.wallConfig.height / 2) + ((zone.layer - 1) * CONSTANTS.wallConfig.height), (point1.z + point2.z) / 2); + + const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x); + + return ( + + + + + ); + })} + + ))} + + + {zones + .filter((zone: any) => zone.layer === activeLayer) + .map((zone: any) => ( + { + e.stopPropagation(); + if (deletePointOrLine) { + handleDeleteZone(zone.zoneId); + } + }} + /> + ))} + + + {zones.filter((zone: any) => zone.layer === activeLayer).flatMap((zone: any) => ( + zone.points.slice(0, 4).map((point: any, pointIndex: number) => ( + + + + )) + ))} + + + {startPoint && endPoint && ( + + )} + + + ); +}; + export default ZoneGroup; \ No newline at end of file diff --git a/app/src/modules/builder/groups/zoneGroup1.tsx b/app/src/modules/builder/groups/zoneGroup1.tsx index 7104bb0..b0c6638 100644 --- a/app/src/modules/builder/groups/zoneGroup1.tsx +++ b/app/src/modules/builder/groups/zoneGroup1.tsx @@ -1,245 +1,245 @@ -import { useEffect } from "react"; -import * as THREE from 'three'; -import * as Types from '../../../types/world/worldTypes'; -import * as CONSTANTS from "../../../types/world/worldConstants"; -import { useActiveLayer, useSocketStore, useDeleteModels, useDeletePointOrLine, useMovePoint, useToggleView, useUpdateScene, useNewLines, useToolMode } from "../../../store/store"; -import { useThree } from "@react-three/fiber"; -import arrayLineToObject from "../geomentries/lines/lineConvertions/arrayLineToObject"; -import addPointToScene from "../geomentries/points/addPointToScene"; -import addLineToScene from "../geomentries/lines/addLineToScene"; -import removeSoloPoint from "../geomentries/points/removeSoloPoint"; -import removeReferenceLine from "../geomentries/lines/removeReferenceLine"; -import getClosestIntersection from "../geomentries/lines/getClosestIntersection"; -import loadZones from "../geomentries/zones/loadZones"; - -const ZoneGroup = ({ zoneGroup, plane, floorPlanGroupLine, floorPlanGroupPoint, line, lines, currentLayerPoint, dragPointControls, floorPlanGroup, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => { - const { toggleView, setToggleView } = useToggleView(); - const { deleteModels, setDeleteModels } = useDeleteModels(); - const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); - const { toolMode, setToolMode } = useToolMode(); - const { movePoint, setMovePoint } = useMovePoint(); - const { socket } = useSocketStore(); - const { activeLayer } = useActiveLayer(); - const { gl, raycaster, camera, pointer } = useThree(); - const { updateScene, setUpdateScene } = useUpdateScene(); - const { newLines, setNewLines } = useNewLines(); - - useEffect(() => { - if (updateScene) { - loadZones(lines, zoneGroup); - setUpdateScene(false); - } - }, [updateScene]) - - useEffect(() => { - if (toolMode === "Zone") { - setDeletePointOrLine(false); - setMovePoint(false); - setDeleteModels(false); - } else { - removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); - removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); - } - }, [toolMode]) - - useEffect(() => { - - const canvasElement = gl.domElement; - - let drag = false; - let isLeftMouseDown = false; - - const onMouseDown = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = true; - drag = false; - } - }; - - const onMouseUp = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = false; - } - } - - const onMouseMove = () => { - if (isLeftMouseDown) { - drag = true; - } - }; - - const onContextMenu = (e: any) => { - e.preventDefault(); - if (toolMode === "Zone") { - removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); - removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); - } - }; - - const onMouseClick = (evt: any) => { - if (!plane.current || drag) return; - const intersects = raycaster.intersectObject(plane.current, true); - let intersectionPoint = intersects[0].point; - const points = floorPlanGroupPoint.current?.children ?? []; - const intersectsPoint = raycaster.intersectObjects(points, true).find(intersect => intersect.object.visible); - let intersectsLines: any = raycaster.intersectObjects(floorPlanGroupLine.current.children, true); - - if (intersectsLines.length > 0 && intersects && intersects.length > 0 && !intersectsPoint) { - const lineType = intersectsLines[0].object.userData.linePoints[0][3]; - if (lineType === CONSTANTS.lineConfig.zoneName) { - // console.log("intersected a zone line"); - - const ThroughPoint = (intersectsLines[0].object.geometry.parameters.path).getPoints(300); - let intersection = getClosestIntersection(ThroughPoint, intersectionPoint); - if (!intersection) return; - const point = addPointToScene(intersection, CONSTANTS.pointConfig.zoneOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.zoneName); - (line.current as Types.Line).push([new THREE.Vector3(intersection.x, 0.01, intersection.z), point.uuid, activeLayer, CONSTANTS.lineConfig.zoneName,]); - if (line.current.length >= 2 && line.current[0] && line.current[1]) { - lines.current.push(line.current as Types.Line); - - const data = arrayLineToObject(line.current as Types.Line); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setLine(organization, data.layer!, data.line!, data.type!); - - //SOCKET - - const input = { - organization: organization, - layer: data.layer, - line: data.line, - type: data.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input); - - setNewLines([line.current]); - - addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.zoneColor, line.current, floorPlanGroupLine); - let lastPoint = line.current[line.current.length - 1]; - line.current = [lastPoint]; - } - } - } else if (intersectsPoint && intersects && intersects.length > 0) { - if (intersectsPoint.object.userData.type === CONSTANTS.lineConfig.zoneName) { - // console.log("intersected a zone point"); - - intersectionPoint = intersectsPoint.object.position; - (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), intersectsPoint.object.uuid, activeLayer, CONSTANTS.lineConfig.zoneName]); - if (line.current.length >= 2 && line.current[0] && line.current[1]) { - lines.current.push(line.current as Types.Line); - - const data = arrayLineToObject(line.current as Types.Line); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setLine(organization, data.layer!, data.line!, data.type!); - - //SOCKET - - const input = { - organization: organization, - layer: data.layer, - line: data.line, - type: data.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input); - - setNewLines([line.current]); - - addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.zoneColor, line.current, floorPlanGroupLine); - let lastPoint = line.current[line.current.length - 1]; - line.current = [lastPoint]; - ispreSnapped.current = false; - isSnapped.current = false; - } - } - } else if (intersects && intersects.length > 0) { - // console.log("intersected a empty area"); - - let uuid: string = ""; - if (isAngleSnapped.current && anglesnappedPoint.current && line.current.length > 0) { - intersectionPoint = anglesnappedPoint.current; - const point = addPointToScene(intersectionPoint, CONSTANTS.pointConfig.zoneOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.zoneName); - uuid = point.uuid; - } else if (isSnapped.current && snappedPoint.current && line.current.length > 0) { - intersectionPoint = snappedPoint.current; - uuid = isSnappedUUID.current!; - } else if (ispreSnapped.current && snappedPoint.current) { - intersectionPoint = snappedPoint.current; - uuid = isSnappedUUID.current!; - } else { - const point = addPointToScene(intersectionPoint, CONSTANTS.pointConfig.zoneOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.zoneName); - uuid = point.uuid; - } - - (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), uuid, activeLayer, CONSTANTS.lineConfig.zoneName]); - if (line.current.length >= 2 && line.current[0] && line.current[1]) { - lines.current.push(line.current as Types.Line); - - const data = arrayLineToObject(line.current as Types.Line); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setLine(organization, data.layer!, data.line!, data.type!); - - //SOCKET - - const input = { - organization: organization, - layer: data.layer, - line: data.line, - type: data.type, - socketId: socket.id - } - - socket.emit('v1:Line:create', input); - - setNewLines([line.current]); - - addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.zoneColor, line.current, floorPlanGroupLine); - let lastPoint = line.current[line.current.length - 1]; - line.current = [lastPoint]; - ispreSnapped.current = false; - isSnapped.current = false; - } - } - } - - if (toolMode === 'Zone') { - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - canvasElement.addEventListener("click", onMouseClick); - canvasElement.addEventListener("contextmenu", onContextMenu); - } - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - canvasElement.removeEventListener("click", onMouseClick); - canvasElement.removeEventListener("contextmenu", onContextMenu); - }; - }, [toolMode]) - - return ( - - - ) -} - +import { useEffect } from "react"; +import * as THREE from 'three'; +import * as Types from '../../../types/world/worldTypes'; +import * as CONSTANTS from "../../../types/world/worldConstants"; +import { useActiveLayer, useSocketStore, useDeleteModels, useDeletePointOrLine, useMovePoint, useToggleView, useUpdateScene, useNewLines, useToolMode } from "../../../store/store"; +import { useThree } from "@react-three/fiber"; +import arrayLineToObject from "../geomentries/lines/lineConvertions/arrayLineToObject"; +import addPointToScene from "../geomentries/points/addPointToScene"; +import addLineToScene from "../geomentries/lines/addLineToScene"; +import removeSoloPoint from "../geomentries/points/removeSoloPoint"; +import removeReferenceLine from "../geomentries/lines/removeReferenceLine"; +import getClosestIntersection from "../geomentries/lines/getClosestIntersection"; +import loadZones from "../geomentries/zones/loadZones"; + +const ZoneGroup = ({ zoneGroup, plane, floorPlanGroupLine, floorPlanGroupPoint, line, lines, currentLayerPoint, dragPointControls, floorPlanGroup, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => { + const { toggleView, setToggleView } = useToggleView(); + const { deleteModels, setDeleteModels } = useDeleteModels(); + const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); + const { toolMode, setToolMode } = useToolMode(); + const { movePoint, setMovePoint } = useMovePoint(); + const { socket } = useSocketStore(); + const { activeLayer } = useActiveLayer(); + const { gl, raycaster, camera, pointer } = useThree(); + const { updateScene, setUpdateScene } = useUpdateScene(); + const { newLines, setNewLines } = useNewLines(); + + useEffect(() => { + if (updateScene) { + loadZones(lines, zoneGroup); + setUpdateScene(false); + } + }, [updateScene]) + + useEffect(() => { + if (toolMode === "Zone") { + setDeletePointOrLine(false); + setMovePoint(false); + setDeleteModels(false); + } else { + removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); + removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); + } + }, [toolMode]) + + useEffect(() => { + + const canvasElement = gl.domElement; + + let drag = false; + let isLeftMouseDown = false; + + const onMouseDown = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = true; + drag = false; + } + }; + + const onMouseUp = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = false; + } + } + + const onMouseMove = () => { + if (isLeftMouseDown) { + drag = true; + } + }; + + const onContextMenu = (e: any) => { + e.preventDefault(); + if (toolMode === "Zone") { + removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint); + removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); + } + }; + + const onMouseClick = (evt: any) => { + if (!plane.current || drag) return; + const intersects = raycaster.intersectObject(plane.current, true); + let intersectionPoint = intersects[0].point; + const points = floorPlanGroupPoint.current?.children ?? []; + const intersectsPoint = raycaster.intersectObjects(points, true).find(intersect => intersect.object.visible); + let intersectsLines: any = raycaster.intersectObjects(floorPlanGroupLine.current.children, true); + + if (intersectsLines.length > 0 && intersects && intersects.length > 0 && !intersectsPoint) { + const lineType = intersectsLines[0].object.userData.linePoints[0][3]; + if (lineType === CONSTANTS.lineConfig.zoneName) { + // console.log("intersected a zone line"); + + const ThroughPoint = (intersectsLines[0].object.geometry.parameters.path).getPoints(300); + let intersection = getClosestIntersection(ThroughPoint, intersectionPoint); + if (!intersection) return; + const point = addPointToScene(intersection, CONSTANTS.pointConfig.zoneOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.zoneName); + (line.current as Types.Line).push([new THREE.Vector3(intersection.x, 0.01, intersection.z), point.uuid, activeLayer, CONSTANTS.lineConfig.zoneName,]); + if (line.current.length >= 2 && line.current[0] && line.current[1]) { + lines.current.push(line.current as Types.Line); + + const data = arrayLineToObject(line.current as Types.Line); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setLine(organization, data.layer!, data.line!, data.type!); + + //SOCKET + + const input = { + organization: organization, + layer: data.layer, + line: data.line, + type: data.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input); + + setNewLines([line.current]); + + addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.zoneColor, line.current, floorPlanGroupLine); + let lastPoint = line.current[line.current.length - 1]; + line.current = [lastPoint]; + } + } + } else if (intersectsPoint && intersects && intersects.length > 0) { + if (intersectsPoint.object.userData.type === CONSTANTS.lineConfig.zoneName) { + // console.log("intersected a zone point"); + + intersectionPoint = intersectsPoint.object.position; + (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), intersectsPoint.object.uuid, activeLayer, CONSTANTS.lineConfig.zoneName]); + if (line.current.length >= 2 && line.current[0] && line.current[1]) { + lines.current.push(line.current as Types.Line); + + const data = arrayLineToObject(line.current as Types.Line); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setLine(organization, data.layer!, data.line!, data.type!); + + //SOCKET + + const input = { + organization: organization, + layer: data.layer, + line: data.line, + type: data.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input); + + setNewLines([line.current]); + + addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.zoneColor, line.current, floorPlanGroupLine); + let lastPoint = line.current[line.current.length - 1]; + line.current = [lastPoint]; + ispreSnapped.current = false; + isSnapped.current = false; + } + } + } else if (intersects && intersects.length > 0) { + // console.log("intersected a empty area"); + + let uuid: string = ""; + if (isAngleSnapped.current && anglesnappedPoint.current && line.current.length > 0) { + intersectionPoint = anglesnappedPoint.current; + const point = addPointToScene(intersectionPoint, CONSTANTS.pointConfig.zoneOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.zoneName); + uuid = point.uuid; + } else if (isSnapped.current && snappedPoint.current && line.current.length > 0) { + intersectionPoint = snappedPoint.current; + uuid = isSnappedUUID.current!; + } else if (ispreSnapped.current && snappedPoint.current) { + intersectionPoint = snappedPoint.current; + uuid = isSnappedUUID.current!; + } else { + const point = addPointToScene(intersectionPoint, CONSTANTS.pointConfig.zoneOuterColor, currentLayerPoint, floorPlanGroupPoint, dragPointControls, undefined, CONSTANTS.lineConfig.zoneName); + uuid = point.uuid; + } + + (line.current as Types.Line).push([new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), uuid, activeLayer, CONSTANTS.lineConfig.zoneName]); + if (line.current.length >= 2 && line.current[0] && line.current[1]) { + lines.current.push(line.current as Types.Line); + + const data = arrayLineToObject(line.current as Types.Line); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setLine(organization, data.layer!, data.line!, data.type!); + + //SOCKET + + const input = { + organization: organization, + layer: data.layer, + line: data.line, + type: data.type, + socketId: socket.id + } + + socket.emit('v1:Line:create', input); + + setNewLines([line.current]); + + addLineToScene(line.current[0][0], line.current[1][0], CONSTANTS.lineConfig.zoneColor, line.current, floorPlanGroupLine); + let lastPoint = line.current[line.current.length - 1]; + line.current = [lastPoint]; + ispreSnapped.current = false; + isSnapped.current = false; + } + } + } + + if (toolMode === 'Zone') { + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + canvasElement.addEventListener("click", onMouseClick); + canvasElement.addEventListener("contextmenu", onContextMenu); + } + + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + canvasElement.removeEventListener("click", onMouseClick); + canvasElement.removeEventListener("contextmenu", onContextMenu); + }; + }, [toolMode]) + + return ( + + + ) +} + export default ZoneGroup; \ No newline at end of file diff --git a/app/src/modules/collaboration/collabCams.tsx b/app/src/modules/collaboration/collabCams.tsx index 900b3d0..da20b34 100644 --- a/app/src/modules/collaboration/collabCams.tsx +++ b/app/src/modules/collaboration/collabCams.tsx @@ -1,142 +1,142 @@ -import * as THREE from 'three'; -import { useEffect, useRef, useState } from 'react'; -import { useFrame } from '@react-three/fiber'; -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; -import camModel from '../../assets/gltf-glb/camera face 2.gltf'; -import getActiveUsersData from '../../services/factoryBuilder/collab/getActiveUsers'; -import { useActiveUsers, useSocketStore } from '../../store/store'; -import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; -import { useNavigate } from 'react-router-dom'; -import { Text, Html } from '@react-three/drei'; -import CollabUserIcon from './collabUserIcon'; -import image from '../../assets/image/userImage.png'; - - -const CamModelsGroup = () => { - let navigate = useNavigate(); - const groupRef = useRef(null); - const email = localStorage.getItem('email'); - const { activeUsers, setActiveUsers } = useActiveUsers(); - const { socket } = useSocketStore(); - const loader = new GLTFLoader(); - const dracoLoader = new DRACOLoader(); - const [cams, setCams] = useState([]); - const [models, setModels] = useState>({}); - - dracoLoader.setDecoderPath('three/examples/jsm/libs/draco/gltf/'); - loader.setDRACOLoader(dracoLoader); - - useEffect(() => { - if (!email) { - navigate('/'); - } - if (!socket) return; - const organization = email!.split('@')[1].split('.')[0]; - - socket.on('userConnectRespones', (data: any) => { - if (!groupRef.current) return; - if (data.data.userData.email === email) return - if (socket.id === data.socketId || organization !== data.organization) return; - - const model = groupRef.current.getObjectByProperty('uuid', data.data.userData._id); - if (model) { - groupRef.current.remove(model); - } - loader.load(camModel, (gltf) => { - const newModel = gltf.scene.clone(); - newModel.uuid = data.data.userData._id; - newModel.position.set(data.data.position.x, data.data.position.y, data.data.position.z); - newModel.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); - newModel.userData = data.data.userData; - setCams((prev) => [...prev, newModel]); - setActiveUsers([...activeUsers, data.data.userData]); - }); - }); - - socket.on('userDisConnectRespones', (data: any) => { - if (!groupRef.current) return; - if (socket.id === data.socketId || organization !== data.organization) return; - - setCams((prev) => prev.filter((cam) => cam.uuid !== data.data.userData._id)); - setActiveUsers(activeUsers.filter((user: any) => user._id !== data.data.userData._id)); - }); - - socket.on('cameraUpdateResponse', (data: any) => { - if (!groupRef.current || socket.id === data.socketId || organization !== data.organization) return; - - setModels((prev) => ({ - ...prev, - [data.data.userId]: { - targetPosition: new THREE.Vector3(data.data.position.x, data.data.position.y, data.data.position.z), - targetRotation: new THREE.Euler(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z), - }, - })); - }); - - return () => { - socket.off('userConnectRespones'); - socket.off('userDisConnectRespones'); - socket.off('cameraUpdateResponse'); - }; - }, [socket]); - - useFrame(() => { - if (!groupRef.current) return; - Object.keys(models).forEach((uuid) => { - const model = groupRef.current!.getObjectByProperty('uuid', uuid); - if (!model) return; - - const { targetPosition, targetRotation } = models[uuid]; - model.position.lerp(targetPosition, 0.1); - model.rotation.x = THREE.MathUtils.lerp(model.rotation.x, targetRotation.x, 0.1); - model.rotation.y = THREE.MathUtils.lerp(model.rotation.y, targetRotation.y, 0.1); - model.rotation.z = THREE.MathUtils.lerp(model.rotation.z, targetRotation.z, 0.1); - }); - }); - - useEffect(() => { - if (!groupRef.current) return; - const organization = email!.split('@')[1].split('.')[0]; - getActiveUsersData(organization).then((data) => { - const filteredData = data.cameraDatas.filter((camera: any) => camera.userData.email !== email); - if (filteredData.length > 0) { - loader.load(camModel, (gltf) => { - const newCams = filteredData.map((cam: any) => { - const newModel = gltf.scene.clone(); - newModel.uuid = cam.userData._id; - newModel.position.set(cam.position.x, cam.position.y, cam.position.z); - newModel.rotation.set(cam.rotation.x, cam.rotation.y, cam.rotation.z); - newModel.userData = cam.userData; - setActiveUsers([...activeUsers, cam.userData]); - return newModel; - }); - setCams((prev) => [...prev, ...newCams]); - }); - } - }); - }, []); - - return ( - - {cams.map((cam, index) => ( - - - - - - ))} - - ); -}; - -export default CamModelsGroup; +import * as THREE from 'three'; +import { useEffect, useRef, useState } from 'react'; +import { useFrame } from '@react-three/fiber'; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import camModel from '../../assets/gltf-glb/camera face 2.gltf'; +import getActiveUsersData from '../../services/factoryBuilder/collab/getActiveUsers'; +import { useActiveUsers, useSocketStore } from '../../store/store'; +import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; +import { useNavigate } from 'react-router-dom'; +import { Text, Html } from '@react-three/drei'; +import CollabUserIcon from './collabUserIcon'; +import image from '../../assets/image/userImage.png'; + + +const CamModelsGroup = () => { + let navigate = useNavigate(); + const groupRef = useRef(null); + const email = localStorage.getItem('email'); + const { activeUsers, setActiveUsers } = useActiveUsers(); + const { socket } = useSocketStore(); + const loader = new GLTFLoader(); + const dracoLoader = new DRACOLoader(); + const [cams, setCams] = useState([]); + const [models, setModels] = useState>({}); + + dracoLoader.setDecoderPath('three/examples/jsm/libs/draco/gltf/'); + loader.setDRACOLoader(dracoLoader); + + useEffect(() => { + if (!email) { + navigate('/'); + } + if (!socket) return; + const organization = email!.split('@')[1].split('.')[0]; + + socket.on('userConnectRespones', (data: any) => { + if (!groupRef.current) return; + if (data.data.userData.email === email) return + if (socket.id === data.socketId || organization !== data.organization) return; + + const model = groupRef.current.getObjectByProperty('uuid', data.data.userData._id); + if (model) { + groupRef.current.remove(model); + } + loader.load(camModel, (gltf) => { + const newModel = gltf.scene.clone(); + newModel.uuid = data.data.userData._id; + newModel.position.set(data.data.position.x, data.data.position.y, data.data.position.z); + newModel.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); + newModel.userData = data.data.userData; + setCams((prev) => [...prev, newModel]); + setActiveUsers([...activeUsers, data.data.userData]); + }); + }); + + socket.on('userDisConnectRespones', (data: any) => { + if (!groupRef.current) return; + if (socket.id === data.socketId || organization !== data.organization) return; + + setCams((prev) => prev.filter((cam) => cam.uuid !== data.data.userData._id)); + setActiveUsers(activeUsers.filter((user: any) => user._id !== data.data.userData._id)); + }); + + socket.on('cameraUpdateResponse', (data: any) => { + if (!groupRef.current || socket.id === data.socketId || organization !== data.organization) return; + + setModels((prev) => ({ + ...prev, + [data.data.userId]: { + targetPosition: new THREE.Vector3(data.data.position.x, data.data.position.y, data.data.position.z), + targetRotation: new THREE.Euler(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z), + }, + })); + }); + + return () => { + socket.off('userConnectRespones'); + socket.off('userDisConnectRespones'); + socket.off('cameraUpdateResponse'); + }; + }, [socket]); + + useFrame(() => { + if (!groupRef.current) return; + Object.keys(models).forEach((uuid) => { + const model = groupRef.current!.getObjectByProperty('uuid', uuid); + if (!model) return; + + const { targetPosition, targetRotation } = models[uuid]; + model.position.lerp(targetPosition, 0.1); + model.rotation.x = THREE.MathUtils.lerp(model.rotation.x, targetRotation.x, 0.1); + model.rotation.y = THREE.MathUtils.lerp(model.rotation.y, targetRotation.y, 0.1); + model.rotation.z = THREE.MathUtils.lerp(model.rotation.z, targetRotation.z, 0.1); + }); + }); + + useEffect(() => { + if (!groupRef.current) return; + const organization = email!.split('@')[1].split('.')[0]; + getActiveUsersData(organization).then((data) => { + const filteredData = data.cameraDatas.filter((camera: any) => camera.userData.email !== email); + if (filteredData.length > 0) { + loader.load(camModel, (gltf) => { + const newCams = filteredData.map((cam: any) => { + const newModel = gltf.scene.clone(); + newModel.uuid = cam.userData._id; + newModel.position.set(cam.position.x, cam.position.y, cam.position.z); + newModel.rotation.set(cam.rotation.x, cam.rotation.y, cam.rotation.z); + newModel.userData = cam.userData; + setActiveUsers([...activeUsers, cam.userData]); + return newModel; + }); + setCams((prev) => [...prev, ...newCams]); + }); + } + }); + }, []); + + return ( + + {cams.map((cam, index) => ( + + + + + + ))} + + ); +}; + +export default CamModelsGroup; diff --git a/app/src/modules/collaboration/collabUserIcon.tsx b/app/src/modules/collaboration/collabUserIcon.tsx index 4113f6a..a6c22c0 100644 --- a/app/src/modules/collaboration/collabUserIcon.tsx +++ b/app/src/modules/collaboration/collabUserIcon.tsx @@ -1,53 +1,53 @@ -import React from "react"; - -interface CollabUserIconProps { - color: string; - userImage: string; - userName: string; -} - -const CollabUserIcon: React.FC = ({ - color, - userImage, - userName, -}) => { - return ( -
- {userName} -
- {userName} -
-
- ); -}; - -export default CollabUserIcon; +import React from "react"; + +interface CollabUserIconProps { + color: string; + userImage: string; + userName: string; +} + +const CollabUserIcon: React.FC = ({ + color, + userImage, + userName, +}) => { + return ( +
+ {userName} +
+ {userName} +
+
+ ); +}; + +export default CollabUserIcon; diff --git a/app/src/modules/collaboration/socketResponses.dev.tsx b/app/src/modules/collaboration/socketResponses.dev.tsx index b8dfc2c..e9ca9e0 100644 --- a/app/src/modules/collaboration/socketResponses.dev.tsx +++ b/app/src/modules/collaboration/socketResponses.dev.tsx @@ -1,777 +1,777 @@ -import { useEffect } from "react"; -import * as THREE from 'three'; -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; -import gsap from 'gsap'; -import { toast } from 'react-toastify'; -import { useSocketStore, useActiveLayer, useWallItems, useFloorItems, useLayers, useUpdateScene, useWalls, useDeletedLines, useNewLines, useZonePoints, useZones } from "../../store/store"; - -import * as Types from "../../types/world/worldTypes"; -import * as CONSTANTS from '../../types/world/worldConstants'; -import TempLoader from "../builder/geomentries/assets/tempLoader"; - -// import { setFloorItemApi } from "../../services/factoryBuilder/assest/floorAsset/setFloorItemApi"; -import objectLineToArray from "../builder/geomentries/lines/lineConvertions/objectLineToArray"; -import addLineToScene from "../builder/geomentries/lines/addLineToScene"; -import updateLinesPositions from "../builder/geomentries/lines/updateLinesPositions"; -import updateLines from "../builder/geomentries/lines/updateLines"; -import updateDistanceText from "../builder/geomentries/lines/updateDistanceText"; -import updateFloorLines from "../builder/geomentries/floors/updateFloorLines"; -import loadWalls from "../builder/geomentries/walls/loadWalls"; -import RemoveConnectedLines from "../builder/geomentries/lines/removeConnectedLines"; -import Layer2DVisibility from "../builder/geomentries/layers/layer2DVisibility"; -import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; -import { retrieveGLTF, storeGLTF } from "../../utils/indexDB/idbUtils"; -import { getZonesApi } from "../../services/factoryBuilder/zones/getZonesApi"; - - -export default function SocketResponses({ - floorPlanGroup, - lines, - floorGroup, - floorGroupAisle, - scene, - onlyFloorlines, - AssetConfigurations, - itemsGroup, - isTempLoader, - tempLoader, - currentLayerPoint, - floorPlanGroupPoint, - floorPlanGroupLine, - zoneGroup, - dragPointControls -}: any) { - - const { socket } = useSocketStore(); - const { activeLayer, setActiveLayer } = useActiveLayer(); - const { wallItems, setWallItems } = useWallItems(); - const { layers, setLayers } = useLayers(); - const { floorItems, setFloorItems } = useFloorItems(); - const { updateScene, setUpdateScene } = useUpdateScene(); - const { walls, setWalls } = useWalls(); - const { deletedLines, setDeletedLines } = useDeletedLines(); - const { newLines, setNewLines } = useNewLines(); - const { zones, setZones } = useZones(); - const { zonePoints, setZonePoints } = useZonePoints(); - - useEffect(() => { - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - if (!socket) return - - socket.on('cameraCreateResponse', (data: any) => { - // console.log('data: ', data); - }) - - socket.on('userConnectRespones', (data: any) => { - // console.log('data: ', data); - }) - - socket.on('userDisConnectRespones', (data: any) => { - // console.log('data: ', data); - }) - - socket.on('cameraUpdateResponse', (data: any) => { - // console.log('data: ', data); - }) - - socket.on('EnvironmentUpdateResponse', (data: any) => { - // console.log('data: ', data); - }) - - socket.on('FloorItemsUpdateResponse', async (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "flooritem created") { - const loader = new GLTFLoader(); - const dracoLoader = new DRACOLoader(); - - dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); - loader.setDRACOLoader(dracoLoader); - let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; - - try { - isTempLoader.current = true; - const cachedModel = THREE.Cache.get(data.data.modelname); - let url; - - if (cachedModel) { - // console.log(`Getting ${data.data.modelname} from cache`); - url = URL.createObjectURL(cachedModel); - } else { - const indexedDBModel = await retrieveGLTF(data.data.modelname); - if (indexedDBModel) { - // console.log(`Getting ${data.data.modelname} from IndexedDB`); - url = URL.createObjectURL(indexedDBModel); - } else { - // console.log(`Getting ${data.data.modelname} from Backend`); - url = `${url_Backend_dwinzo}/api/v1/AssetFile/${data.data.modelfileID}`; - const modelBlob = await fetch(url).then((res) => res.blob()); - await storeGLTF(data.data.modelfileID, modelBlob); - } - } - - loadModel(url); - - } catch (error) { - console.error('Error fetching asset model:', error); - } - - function loadModel(url: string) { - loader.load(url, (gltf) => { - URL.revokeObjectURL(url); - THREE.Cache.remove(url); - const model = gltf.scene; - model.uuid = data.data.modeluuid; - model.userData = { name: data.data.modelname, modelId: data.data.modelFileID }; - model.position.set(...data.data.position as [number, number, number]); - model.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); - model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); - - model.traverse((child: any) => { - if (child.isMesh) { - // Clone the material to ensure changes are independent - // child.material = child.material.clone(); - - child.castShadow = true; - child.receiveShadow = true; - } - }); - - itemsGroup.current.add(model); - - if (tempLoader.current) { - tempLoader.current.material.dispose(); - tempLoader.current.geometry.dispose(); - itemsGroup.current.remove(tempLoader.current); - tempLoader.current = undefined; - } - - const newFloorItem: Types.FloorItemType = { - modeluuid: data.data.modeluuid, - modelname: data.data.modelname, - modelfileID: data.data.modelfileID, - position: [...data.data.position as [number, number, number]], - rotation: { - x: model.rotation.x, - y: model.rotation.y, - z: model.rotation.z, - }, - isLocked: data.data.isLocked, - isVisible: data.data.isVisible, - }; - - setFloorItems((prevItems: any) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); - - gsap.to(model.position, { y: data.data.position[1], duration: 1.5, ease: 'power2.out' }); - gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out', onComplete: () => { toast.success("Model Added!") } }); - - THREE.Cache.add(data.data.modelname, gltf); - }, () => { - TempLoader(new THREE.Vector3(...data.data.position), isTempLoader, tempLoader, itemsGroup); - }); - } - - } else if (data.message === "flooritems updated") { - itemsGroup.current.children.forEach((item: THREE.Group) => { - if (item.uuid === data.data.modeluuid) { - item.position.set(...data.data.position as [number, number, number]); - item.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); - } - }) - - setFloorItems((prevItems: Types.FloorItems) => { - if (!prevItems) { - return - } - let updatedItem: any = null; - const updatedItems = prevItems.map((item) => { - if (item.modeluuid === data.data.modeluuid) { - updatedItem = { - ...item, - position: [...data.data.position] as [number, number, number], - rotation: { x: data.data.rotation.x, y: data.data.rotation.y, z: data.data.rotation.z, }, - }; - return updatedItem; - } - return item; - }); - return updatedItems; - }) - } - }) - - socket.on('FloorItemsDeleteResponse', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "flooritem deleted") { - const deletedUUID = data.data.modeluuid; - let items = JSON.parse(localStorage.getItem("FloorItems")!); - - const updatedItems = items.filter( - (item: { modeluuid: string }) => item.modeluuid !== deletedUUID - ); - - const storedItems = JSON.parse(localStorage.getItem("FloorItems") || '[]'); - const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => item.modeluuid !== deletedUUID); - localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); - - itemsGroup.current.children.forEach((item: any) => { - if (item.uuid === deletedUUID) { - itemsGroup.current.remove(item); - } - }) - setFloorItems(updatedItems); - toast.success("Model Removed!"); - } - }) - - socket.on('Line:response:update', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "line updated") { - const DraggedUUID = data.data.uuid; - const DraggedPosition = new THREE.Vector3(data.data.position.x, data.data.position.y, data.data.position.z); - - const point = floorPlanGroupPoint.current.getObjectByProperty('uuid', DraggedUUID); - point.position.set(DraggedPosition.x, DraggedPosition.y, DraggedPosition.z); - const affectedLines = updateLinesPositions({ uuid: DraggedUUID, position: DraggedPosition }, lines); - - updateLines(floorPlanGroupLine, affectedLines); - updateDistanceText(scene, floorPlanGroupLine, affectedLines); - updateFloorLines(onlyFloorlines, { uuid: DraggedUUID, position: DraggedPosition }); - - loadWalls(lines, setWalls); - setUpdateScene(true); - - } - }) - - socket.on('Line:response:delete', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "line deleted") { - const line = objectLineToArray(data.data); - const linePoints = line; - const connectedpoints = [linePoints[0][1], linePoints[1][1]]; - - - onlyFloorlines.current = onlyFloorlines.current.map((floorline: any) => - floorline.filter((line: any) => line[0][1] !== connectedpoints[0] && line[1][1] !== connectedpoints[1]) - ).filter((floorline: any) => floorline.length > 0); - - const removedLine = lines.current.find((item: any) => (item[0][1] === linePoints[0][1] && item[1][1] === linePoints[1][1] || (item[0][1] === linePoints[1][1] && item[1][1] === linePoints[0][1]))); - lines.current = lines.current.filter((item: any) => item !== removedLine); - - floorPlanGroupLine.current.children.forEach((line: any) => { - const linePoints = line.userData.linePoints as [number, string, number][]; - const uuid1 = linePoints[0][1]; - const uuid2 = linePoints[1][1]; - - if ((uuid1 === connectedpoints[0] && uuid2 === connectedpoints[1] || (uuid1 === connectedpoints[1] && uuid2 === connectedpoints[0]))) { - line.material.dispose(); - line.geometry.dispose(); - floorPlanGroupLine.current.remove(line); - setDeletedLines([line.userData.linePoints]) - } - }); - - connectedpoints.forEach((pointUUID) => { - let isConnected = false; - floorPlanGroupLine.current.children.forEach((line: any) => { - const linePoints = line.userData.linePoints; - const uuid1 = linePoints[0][1]; - const uuid2 = linePoints[1][1]; - if (uuid1 === pointUUID || uuid2 === pointUUID) { - isConnected = true; - } - }); - - if (!isConnected) { - floorPlanGroupPoint.current.children.forEach((point: any) => { - if (point.uuid === pointUUID) { - point.material.dispose(); - point.geometry.dispose(); - floorPlanGroupPoint.current.remove(point); - } - }); - } - }); - - loadWalls(lines, setWalls); - setUpdateScene(true); - - toast.success("Line Removed!"); - } - }) - - socket.on('Line:response:delete:point', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "point deleted") { - const point = floorPlanGroupPoint.current?.getObjectByProperty('uuid', data.data); - point.material.dispose(); - point.geometry.dispose(); - floorPlanGroupPoint.current.remove(point); - - onlyFloorlines.current = onlyFloorlines.current.map((floorline: any) => - floorline.filter((line: any) => line[0][1] !== data.data && line[1][1] !== data.data) - ).filter((floorline: any) => floorline.length > 0); - - RemoveConnectedLines(data.data, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, lines); - - loadWalls(lines, setWalls); - setUpdateScene(true); - - toast.success("Point Removed!"); - } - }) - - socket.on('Line:response:delete:layer', async (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "layer deleted") { - setActiveLayer(1) - const removedLayer = data.data; - const removedLines: Types.Lines = lines.current.filter((line: any) => line[0][2] === removedLayer); - - ////////// Remove Points and lines from the removed layer ////////// - - removedLines.forEach(async (line) => { - line.forEach(async (removedPoint) => { - const removableLines: THREE.Mesh[] = []; - const connectedpoints: string[] = []; - - floorPlanGroupLine.current.children.forEach((line: any) => { - const linePoints = line.userData.linePoints as [number, string, number][]; - const uuid1 = linePoints[0][1]; - const uuid2 = linePoints[1][1]; - - if (uuid1 === removedPoint[1] || uuid2 === removedPoint[1]) { - connectedpoints.push(uuid1 === removedPoint[1] ? uuid2 : uuid1); - removableLines.push(line as THREE.Mesh); - } - }); - - if (removableLines.length > 0) { - removableLines.forEach((line: any) => { - lines.current = lines.current.filter((item: any) => JSON.stringify(item) !== JSON.stringify(line.userData.linePoints)); - line.material.dispose(); - line.geometry.dispose(); - floorPlanGroupLine.current.remove(line); - }); - } - - const point = floorPlanGroupPoint.current.getObjectByProperty('uuid', removedPoint[1]); - if (point) { - point.material.dispose(); - point.geometry.dispose(); - floorPlanGroupPoint.current.remove(point) - } - }); - }); - - ////////// Update the remaining lines layer values in the userData and in lines.current ////////// - - let remaining = lines.current.filter((line: any) => line[0][2] !== removedLayer); - let updatedLines: Types.Lines = []; - remaining.forEach((line: any) => { - let newLines = JSON.parse(JSON.stringify(line)); - if (newLines[0][2] > removedLayer) { - newLines[0][2] -= 1; - newLines[1][2] -= 1; - } - - const matchingLine = floorPlanGroupLine.current.children.find((l: any) => l.userData.linePoints[0][1] === line[0][1] && l.userData.linePoints[1][1] === line[1][1]); - if (matchingLine) { - const updatedUserData = JSON.parse(JSON.stringify(matchingLine.userData)); - updatedUserData.linePoints[0][2] = newLines[0][2]; - updatedUserData.linePoints[1][2] = newLines[1][2]; - matchingLine.userData = updatedUserData; - } - updatedLines.push(newLines); - }); - - lines.current = updatedLines; - localStorage.setItem("Lines", JSON.stringify(lines.current)); - - ////////// Also remove OnlyFloorLines and update it in localstorage ////////// - - onlyFloorlines.current = onlyFloorlines.current.filter((floor: any) => { - return floor[0][0][2] !== removedLayer; - }); - const meshToRemove = floorGroup.current?.children.find((mesh: any) => - mesh.name === `Only_Floor_Line_${removedLayer}` - ); - if (meshToRemove) { - meshToRemove.geometry.dispose(); - meshToRemove.material.dispose(); - floorGroup.current?.remove(meshToRemove); - } - - const zonesData = await getZonesApi(organization); - const highestLayer = Math.max( - 1, - lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), - zonesData.data.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) - ); - - setLayers(highestLayer); - - loadWalls(lines, setWalls); - setUpdateScene(true); - - toast.success("Layer Removed!"); - } - }) - }, [socket]) - - useEffect(() => { - if (!socket) return - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - socket.on('wallItemsDeleteResponse', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "wallitem deleted") { - const deletedUUID = data.data.modeluuid; - let WallItemsRef = wallItems; - const Items = WallItemsRef.filter((item: any) => item.model?.uuid !== deletedUUID); - - setWallItems([]); - setTimeout(async () => { - WallItemsRef = Items; - setWallItems(WallItemsRef); - const WallItemsForStorage = WallItemsRef.map((item: any) => { - const { model, ...rest } = item; - return { - ...rest, - modeluuid: model?.uuid, - }; - }); - - localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); - toast.success("Model Removed!"); - }, 50); - } - }) - - socket.on('wallItemsUpdateResponse', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "wallIitem created") { - const loader = new GLTFLoader(); - loader.load(AssetConfigurations[data.data.modelname].modelUrl, async (gltf) => { - const model = gltf.scene; - model.uuid = data.data.modeluuid; - model.children[0].children.forEach((child) => { - if (child.name !== "CSG_REF") { - child.castShadow = true; - child.receiveShadow = true; - } - }); - - const newWallItem = { - type: data.data.type, - model: model, - modelname: data.data.modelname, - scale: data.data.scale, - csgscale: data.data.csgscale, - csgposition: data.data.csgposition, - position: data.data.position, - quaternion: data.data.quaternion - }; - - setWallItems((prevItems: any) => { - const updatedItems = [...prevItems, newWallItem]; - - const WallItemsForStorage = updatedItems.map(item => { - const { model, ...rest } = item; - return { - ...rest, - modeluuid: model?.uuid, - }; - }); - - localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); - toast.success("Model Added!"); - - return updatedItems; - }); - }); - } else if (data.message === "wallIitem updated") { - const updatedUUID = data.data.modeluuid; - - setWallItems((prevItems: any) => { - const updatedItems = prevItems.map((item: any) => { - if (item.model.uuid === updatedUUID) { - return { - ...item, - position: data.data.position, - quaternion: data.data.quaternion, - scale: data.data.scale, - csgscale: data.data.csgscale, - csgposition: data.data.csgposition, - }; - } - return item; - }); - - const WallItemsForStorage = updatedItems.map((item: any) => { - const { model, ...rest } = item; - return { - ...rest, - modeluuid: model?.uuid, - }; - }); - - localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); - toast.success("Model Updated!"); - - return updatedItems; - }); - - } - - }) - - return () => { - socket.off('wallItemsDeleteResponse'); - socket.off('wallItemsUpdateResponse'); - }; - }, [wallItems]) - - function getPointColor(lineType: string | undefined): string { - switch (lineType) { - case CONSTANTS.lineConfig.wallName: return CONSTANTS.pointConfig.wallOuterColor; - case CONSTANTS.lineConfig.floorName: return CONSTANTS.pointConfig.floorOuterColor; - case CONSTANTS.lineConfig.aisleName: return CONSTANTS.pointConfig.aisleOuterColor; - default: return CONSTANTS.pointConfig.defaultOuterColor; - } - } - - function getLineColor(lineType: string | undefined): string { - switch (lineType) { - case CONSTANTS.lineConfig.wallName: return CONSTANTS.lineConfig.wallColor; - case CONSTANTS.lineConfig.floorName: return CONSTANTS.lineConfig.floorColor; - case CONSTANTS.lineConfig.aisleName: return CONSTANTS.lineConfig.aisleColor; - default: return CONSTANTS.lineConfig.defaultColor; - } - } - - useEffect(() => { - if (!socket) return - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - socket.on('Line:response:create', async (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "line create") { - const line: Types.Line = objectLineToArray(data.data); - const type = line[0][3]; - const pointColour = getPointColor(type); - const lineColour = getLineColor(type); - setNewLines([line]) - - line.forEach((line) => { - const existingPoint = floorPlanGroupPoint.current?.getObjectByProperty('uuid', line[1]); - if (existingPoint) { - return; - } - const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale); - const material = new THREE.ShaderMaterial({ - uniforms: { - uColor: { value: new THREE.Color(pointColour) }, // Blue color for the border - uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square - }, - vertexShader: ` - varying vec2 vUv; - - void main() { - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); - } - `, - fragmentShader: ` - varying vec2 vUv; - uniform vec3 uColor; - uniform vec3 uInnerColor; - - void main() { - // Define the size of the white square as a proportion of the face - float borderThickness = 0.2; // Adjust this value for border thickness - if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && - vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) { - gl_FragColor = vec4(uInnerColor, 1.0); // White inner square - } else { - gl_FragColor = vec4(uColor, 1.0); // Blue border - } - } - `, - }); - const point = new THREE.Mesh(geometry, material); - point.name = "point"; - point.uuid = line[1]; - point.userData = { type: type, color: pointColour }; - point.position.set(line[0].x, line[0].y, line[0].z); - currentLayerPoint.current.push(point); - - floorPlanGroupPoint.current?.add(point); - }) - if (dragPointControls.current) { - dragPointControls.current!.objects = currentLayerPoint.current; - } - addLineToScene( - new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z), - new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z), - lineColour, - line, - floorPlanGroupLine - ) - lines.current.push(line); - - const zonesData = await getZonesApi(organization); - const highestLayer = Math.max( - 1, - lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), - zonesData.data.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) - ); - - setLayers(highestLayer); - - Layer2DVisibility(activeLayer, floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, currentLayerPoint, dragPointControls) - - loadWalls(lines, setWalls); - setUpdateScene(true); - } - }) - - return () => { - socket.off('Line:response:create'); - }; - }, [socket, activeLayer]) - - useEffect(() => { - if (!socket) return - const email = localStorage.getItem('email'); - const organization = (email!.split("@")[1]).split(".")[0]; - - socket.on('zone:response:updates', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - - if (data.message === "zone created") { - const pointsArray: [number, number, number][] = data.data.points; - const vector3Array = pointsArray.map(([x, y, z]) => new THREE.Vector3(x, y, z)); - const newZones = [...zones, data.data]; - setZones(newZones); - const updatedZonePoints = [...zonePoints, ...vector3Array]; - setZonePoints(updatedZonePoints); - - const highestLayer = Math.max( - 1, - lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), - newZones.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) - ); - - setLayers(highestLayer); - setUpdateScene(true); - } - - if (data.message === "zone updated") { - const updatedZones = zones.map((zone: any) => - zone.zoneId === data.data.zoneId ? data.data : zone - ); - setZones(updatedZones); - setUpdateScene(true); - } - - - }) - - socket.on('zone:response:delete', (data: any) => { - if (socket.id === data.socketId) { - return - } - if (organization !== data.organization) { - return - } - if (data.message === "zone deleted") { - const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId); - setZones(updatedZones); - - const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === data.data.zoneId); - if (zoneIndex !== -1) { - const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4); - setZonePoints(updatedzonePoints); - } - - const highestLayer = Math.max( - 1, - lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), - updatedZones.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) - ); - - setLayers(highestLayer); - setUpdateScene(true); - } - }) - - return () => { - socket.off('zone:response:updates'); - socket.off('zone:response:updates'); - }; - }, [socket, zones, zonePoints]) - - return ( - <> - ) +import { useEffect } from "react"; +import * as THREE from 'three'; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import gsap from 'gsap'; +import { toast } from 'react-toastify'; +import { useSocketStore, useActiveLayer, useWallItems, useFloorItems, useLayers, useUpdateScene, useWalls, useDeletedLines, useNewLines, useZonePoints, useZones } from "../../store/store"; + +import * as Types from "../../types/world/worldTypes"; +import * as CONSTANTS from '../../types/world/worldConstants'; +import TempLoader from "../builder/geomentries/assets/tempLoader"; + +// import { setFloorItemApi } from "../../services/factoryBuilder/assest/floorAsset/setFloorItemApi"; +import objectLineToArray from "../builder/geomentries/lines/lineConvertions/objectLineToArray"; +import addLineToScene from "../builder/geomentries/lines/addLineToScene"; +import updateLinesPositions from "../builder/geomentries/lines/updateLinesPositions"; +import updateLines from "../builder/geomentries/lines/updateLines"; +import updateDistanceText from "../builder/geomentries/lines/updateDistanceText"; +import updateFloorLines from "../builder/geomentries/floors/updateFloorLines"; +import loadWalls from "../builder/geomentries/walls/loadWalls"; +import RemoveConnectedLines from "../builder/geomentries/lines/removeConnectedLines"; +import Layer2DVisibility from "../builder/geomentries/layers/layer2DVisibility"; +import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; +import { retrieveGLTF, storeGLTF } from "../../utils/indexDB/idbUtils"; +import { getZonesApi } from "../../services/factoryBuilder/zones/getZonesApi"; + + +export default function SocketResponses({ + floorPlanGroup, + lines, + floorGroup, + floorGroupAisle, + scene, + onlyFloorlines, + AssetConfigurations, + itemsGroup, + isTempLoader, + tempLoader, + currentLayerPoint, + floorPlanGroupPoint, + floorPlanGroupLine, + zoneGroup, + dragPointControls +}: any) { + + const { socket } = useSocketStore(); + const { activeLayer, setActiveLayer } = useActiveLayer(); + const { wallItems, setWallItems } = useWallItems(); + const { layers, setLayers } = useLayers(); + const { floorItems, setFloorItems } = useFloorItems(); + const { updateScene, setUpdateScene } = useUpdateScene(); + const { walls, setWalls } = useWalls(); + const { deletedLines, setDeletedLines } = useDeletedLines(); + const { newLines, setNewLines } = useNewLines(); + const { zones, setZones } = useZones(); + const { zonePoints, setZonePoints } = useZonePoints(); + + useEffect(() => { + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + if (!socket) return + + socket.on('cameraCreateResponse', (data: any) => { + // console.log('data: ', data); + }) + + socket.on('userConnectRespones', (data: any) => { + // console.log('data: ', data); + }) + + socket.on('userDisConnectRespones', (data: any) => { + // console.log('data: ', data); + }) + + socket.on('cameraUpdateResponse', (data: any) => { + // console.log('data: ', data); + }) + + socket.on('EnvironmentUpdateResponse', (data: any) => { + // console.log('data: ', data); + }) + + socket.on('FloorItemsUpdateResponse', async (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + if (data.message === "flooritem created") { + const loader = new GLTFLoader(); + const dracoLoader = new DRACOLoader(); + + dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); + loader.setDRACOLoader(dracoLoader); + let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; + + try { + isTempLoader.current = true; + const cachedModel = THREE.Cache.get(data.data.modelname); + let url; + + if (cachedModel) { + // console.log(`Getting ${data.data.modelname} from cache`); + url = URL.createObjectURL(cachedModel); + } else { + const indexedDBModel = await retrieveGLTF(data.data.modelname); + if (indexedDBModel) { + // console.log(`Getting ${data.data.modelname} from IndexedDB`); + url = URL.createObjectURL(indexedDBModel); + } else { + // console.log(`Getting ${data.data.modelname} from Backend`); + url = `${url_Backend_dwinzo}/api/v1/AssetFile/${data.data.modelfileID}`; + const modelBlob = await fetch(url).then((res) => res.blob()); + await storeGLTF(data.data.modelfileID, modelBlob); + } + } + + loadModel(url); + + } catch (error) { + console.error('Error fetching asset model:', error); + } + + function loadModel(url: string) { + loader.load(url, (gltf) => { + URL.revokeObjectURL(url); + THREE.Cache.remove(url); + const model = gltf.scene; + model.uuid = data.data.modeluuid; + model.userData = { name: data.data.modelname, modelId: data.data.modelFileID }; + model.position.set(...data.data.position as [number, number, number]); + model.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); + model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); + + model.traverse((child: any) => { + if (child.isMesh) { + // Clone the material to ensure changes are independent + // child.material = child.material.clone(); + + child.castShadow = true; + child.receiveShadow = true; + } + }); + + itemsGroup.current.add(model); + + if (tempLoader.current) { + tempLoader.current.material.dispose(); + tempLoader.current.geometry.dispose(); + itemsGroup.current.remove(tempLoader.current); + tempLoader.current = undefined; + } + + const newFloorItem: Types.FloorItemType = { + modeluuid: data.data.modeluuid, + modelname: data.data.modelname, + modelfileID: data.data.modelfileID, + position: [...data.data.position as [number, number, number]], + rotation: { + x: model.rotation.x, + y: model.rotation.y, + z: model.rotation.z, + }, + isLocked: data.data.isLocked, + isVisible: data.data.isVisible, + }; + + setFloorItems((prevItems: any) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + gsap.to(model.position, { y: data.data.position[1], duration: 1.5, ease: 'power2.out' }); + gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out', onComplete: () => { toast.success("Model Added!") } }); + + THREE.Cache.add(data.data.modelname, gltf); + }, () => { + TempLoader(new THREE.Vector3(...data.data.position), isTempLoader, tempLoader, itemsGroup); + }); + } + + } else if (data.message === "flooritems updated") { + itemsGroup.current.children.forEach((item: THREE.Group) => { + if (item.uuid === data.data.modeluuid) { + item.position.set(...data.data.position as [number, number, number]); + item.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); + } + }) + + setFloorItems((prevItems: Types.FloorItems) => { + if (!prevItems) { + return + } + let updatedItem: any = null; + const updatedItems = prevItems.map((item) => { + if (item.modeluuid === data.data.modeluuid) { + updatedItem = { + ...item, + position: [...data.data.position] as [number, number, number], + rotation: { x: data.data.rotation.x, y: data.data.rotation.y, z: data.data.rotation.z, }, + }; + return updatedItem; + } + return item; + }); + return updatedItems; + }) + } + }) + + socket.on('FloorItemsDeleteResponse', (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + if (data.message === "flooritem deleted") { + const deletedUUID = data.data.modeluuid; + let items = JSON.parse(localStorage.getItem("FloorItems")!); + + const updatedItems = items.filter( + (item: { modeluuid: string }) => item.modeluuid !== deletedUUID + ); + + const storedItems = JSON.parse(localStorage.getItem("FloorItems") || '[]'); + const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => item.modeluuid !== deletedUUID); + localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); + + itemsGroup.current.children.forEach((item: any) => { + if (item.uuid === deletedUUID) { + itemsGroup.current.remove(item); + } + }) + setFloorItems(updatedItems); + toast.success("Model Removed!"); + } + }) + + socket.on('Line:response:update', (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + if (data.message === "line updated") { + const DraggedUUID = data.data.uuid; + const DraggedPosition = new THREE.Vector3(data.data.position.x, data.data.position.y, data.data.position.z); + + const point = floorPlanGroupPoint.current.getObjectByProperty('uuid', DraggedUUID); + point.position.set(DraggedPosition.x, DraggedPosition.y, DraggedPosition.z); + const affectedLines = updateLinesPositions({ uuid: DraggedUUID, position: DraggedPosition }, lines); + + updateLines(floorPlanGroupLine, affectedLines); + updateDistanceText(scene, floorPlanGroupLine, affectedLines); + updateFloorLines(onlyFloorlines, { uuid: DraggedUUID, position: DraggedPosition }); + + loadWalls(lines, setWalls); + setUpdateScene(true); + + } + }) + + socket.on('Line:response:delete', (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + if (data.message === "line deleted") { + const line = objectLineToArray(data.data); + const linePoints = line; + const connectedpoints = [linePoints[0][1], linePoints[1][1]]; + + + onlyFloorlines.current = onlyFloorlines.current.map((floorline: any) => + floorline.filter((line: any) => line[0][1] !== connectedpoints[0] && line[1][1] !== connectedpoints[1]) + ).filter((floorline: any) => floorline.length > 0); + + const removedLine = lines.current.find((item: any) => (item[0][1] === linePoints[0][1] && item[1][1] === linePoints[1][1] || (item[0][1] === linePoints[1][1] && item[1][1] === linePoints[0][1]))); + lines.current = lines.current.filter((item: any) => item !== removedLine); + + floorPlanGroupLine.current.children.forEach((line: any) => { + const linePoints = line.userData.linePoints as [number, string, number][]; + const uuid1 = linePoints[0][1]; + const uuid2 = linePoints[1][1]; + + if ((uuid1 === connectedpoints[0] && uuid2 === connectedpoints[1] || (uuid1 === connectedpoints[1] && uuid2 === connectedpoints[0]))) { + line.material.dispose(); + line.geometry.dispose(); + floorPlanGroupLine.current.remove(line); + setDeletedLines([line.userData.linePoints]) + } + }); + + connectedpoints.forEach((pointUUID) => { + let isConnected = false; + floorPlanGroupLine.current.children.forEach((line: any) => { + const linePoints = line.userData.linePoints; + const uuid1 = linePoints[0][1]; + const uuid2 = linePoints[1][1]; + if (uuid1 === pointUUID || uuid2 === pointUUID) { + isConnected = true; + } + }); + + if (!isConnected) { + floorPlanGroupPoint.current.children.forEach((point: any) => { + if (point.uuid === pointUUID) { + point.material.dispose(); + point.geometry.dispose(); + floorPlanGroupPoint.current.remove(point); + } + }); + } + }); + + loadWalls(lines, setWalls); + setUpdateScene(true); + + toast.success("Line Removed!"); + } + }) + + socket.on('Line:response:delete:point', (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + if (data.message === "point deleted") { + const point = floorPlanGroupPoint.current?.getObjectByProperty('uuid', data.data); + point.material.dispose(); + point.geometry.dispose(); + floorPlanGroupPoint.current.remove(point); + + onlyFloorlines.current = onlyFloorlines.current.map((floorline: any) => + floorline.filter((line: any) => line[0][1] !== data.data && line[1][1] !== data.data) + ).filter((floorline: any) => floorline.length > 0); + + RemoveConnectedLines(data.data, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, lines); + + loadWalls(lines, setWalls); + setUpdateScene(true); + + toast.success("Point Removed!"); + } + }) + + socket.on('Line:response:delete:layer', async (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + if (data.message === "layer deleted") { + setActiveLayer(1) + const removedLayer = data.data; + const removedLines: Types.Lines = lines.current.filter((line: any) => line[0][2] === removedLayer); + + ////////// Remove Points and lines from the removed layer ////////// + + removedLines.forEach(async (line) => { + line.forEach(async (removedPoint) => { + const removableLines: THREE.Mesh[] = []; + const connectedpoints: string[] = []; + + floorPlanGroupLine.current.children.forEach((line: any) => { + const linePoints = line.userData.linePoints as [number, string, number][]; + const uuid1 = linePoints[0][1]; + const uuid2 = linePoints[1][1]; + + if (uuid1 === removedPoint[1] || uuid2 === removedPoint[1]) { + connectedpoints.push(uuid1 === removedPoint[1] ? uuid2 : uuid1); + removableLines.push(line as THREE.Mesh); + } + }); + + if (removableLines.length > 0) { + removableLines.forEach((line: any) => { + lines.current = lines.current.filter((item: any) => JSON.stringify(item) !== JSON.stringify(line.userData.linePoints)); + line.material.dispose(); + line.geometry.dispose(); + floorPlanGroupLine.current.remove(line); + }); + } + + const point = floorPlanGroupPoint.current.getObjectByProperty('uuid', removedPoint[1]); + if (point) { + point.material.dispose(); + point.geometry.dispose(); + floorPlanGroupPoint.current.remove(point) + } + }); + }); + + ////////// Update the remaining lines layer values in the userData and in lines.current ////////// + + let remaining = lines.current.filter((line: any) => line[0][2] !== removedLayer); + let updatedLines: Types.Lines = []; + remaining.forEach((line: any) => { + let newLines = JSON.parse(JSON.stringify(line)); + if (newLines[0][2] > removedLayer) { + newLines[0][2] -= 1; + newLines[1][2] -= 1; + } + + const matchingLine = floorPlanGroupLine.current.children.find((l: any) => l.userData.linePoints[0][1] === line[0][1] && l.userData.linePoints[1][1] === line[1][1]); + if (matchingLine) { + const updatedUserData = JSON.parse(JSON.stringify(matchingLine.userData)); + updatedUserData.linePoints[0][2] = newLines[0][2]; + updatedUserData.linePoints[1][2] = newLines[1][2]; + matchingLine.userData = updatedUserData; + } + updatedLines.push(newLines); + }); + + lines.current = updatedLines; + localStorage.setItem("Lines", JSON.stringify(lines.current)); + + ////////// Also remove OnlyFloorLines and update it in localstorage ////////// + + onlyFloorlines.current = onlyFloorlines.current.filter((floor: any) => { + return floor[0][0][2] !== removedLayer; + }); + const meshToRemove = floorGroup.current?.children.find((mesh: any) => + mesh.name === `Only_Floor_Line_${removedLayer}` + ); + if (meshToRemove) { + meshToRemove.geometry.dispose(); + meshToRemove.material.dispose(); + floorGroup.current?.remove(meshToRemove); + } + + const zonesData = await getZonesApi(organization); + const highestLayer = Math.max( + 1, + lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), + zonesData.data.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) + ); + + setLayers(highestLayer); + + loadWalls(lines, setWalls); + setUpdateScene(true); + + toast.success("Layer Removed!"); + } + }) + }, [socket]) + + useEffect(() => { + if (!socket) return + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + socket.on('wallItemsDeleteResponse', (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + if (data.message === "wallitem deleted") { + const deletedUUID = data.data.modeluuid; + let WallItemsRef = wallItems; + const Items = WallItemsRef.filter((item: any) => item.model?.uuid !== deletedUUID); + + setWallItems([]); + setTimeout(async () => { + WallItemsRef = Items; + setWallItems(WallItemsRef); + const WallItemsForStorage = WallItemsRef.map((item: any) => { + const { model, ...rest } = item; + return { + ...rest, + modeluuid: model?.uuid, + }; + }); + + localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); + toast.success("Model Removed!"); + }, 50); + } + }) + + socket.on('wallItemsUpdateResponse', (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + if (data.message === "wallIitem created") { + const loader = new GLTFLoader(); + loader.load(AssetConfigurations[data.data.modelname].modelUrl, async (gltf) => { + const model = gltf.scene; + model.uuid = data.data.modeluuid; + model.children[0].children.forEach((child) => { + if (child.name !== "CSG_REF") { + child.castShadow = true; + child.receiveShadow = true; + } + }); + + const newWallItem = { + type: data.data.type, + model: model, + modelname: data.data.modelname, + scale: data.data.scale, + csgscale: data.data.csgscale, + csgposition: data.data.csgposition, + position: data.data.position, + quaternion: data.data.quaternion + }; + + setWallItems((prevItems: any) => { + const updatedItems = [...prevItems, newWallItem]; + + const WallItemsForStorage = updatedItems.map(item => { + const { model, ...rest } = item; + return { + ...rest, + modeluuid: model?.uuid, + }; + }); + + localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); + toast.success("Model Added!"); + + return updatedItems; + }); + }); + } else if (data.message === "wallIitem updated") { + const updatedUUID = data.data.modeluuid; + + setWallItems((prevItems: any) => { + const updatedItems = prevItems.map((item: any) => { + if (item.model.uuid === updatedUUID) { + return { + ...item, + position: data.data.position, + quaternion: data.data.quaternion, + scale: data.data.scale, + csgscale: data.data.csgscale, + csgposition: data.data.csgposition, + }; + } + return item; + }); + + const WallItemsForStorage = updatedItems.map((item: any) => { + const { model, ...rest } = item; + return { + ...rest, + modeluuid: model?.uuid, + }; + }); + + localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage)); + toast.success("Model Updated!"); + + return updatedItems; + }); + + } + + }) + + return () => { + socket.off('wallItemsDeleteResponse'); + socket.off('wallItemsUpdateResponse'); + }; + }, [wallItems]) + + function getPointColor(lineType: string | undefined): string { + switch (lineType) { + case CONSTANTS.lineConfig.wallName: return CONSTANTS.pointConfig.wallOuterColor; + case CONSTANTS.lineConfig.floorName: return CONSTANTS.pointConfig.floorOuterColor; + case CONSTANTS.lineConfig.aisleName: return CONSTANTS.pointConfig.aisleOuterColor; + default: return CONSTANTS.pointConfig.defaultOuterColor; + } + } + + function getLineColor(lineType: string | undefined): string { + switch (lineType) { + case CONSTANTS.lineConfig.wallName: return CONSTANTS.lineConfig.wallColor; + case CONSTANTS.lineConfig.floorName: return CONSTANTS.lineConfig.floorColor; + case CONSTANTS.lineConfig.aisleName: return CONSTANTS.lineConfig.aisleColor; + default: return CONSTANTS.lineConfig.defaultColor; + } + } + + useEffect(() => { + if (!socket) return + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + socket.on('Line:response:create', async (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + if (data.message === "line create") { + const line: Types.Line = objectLineToArray(data.data); + const type = line[0][3]; + const pointColour = getPointColor(type); + const lineColour = getLineColor(type); + setNewLines([line]) + + line.forEach((line) => { + const existingPoint = floorPlanGroupPoint.current?.getObjectByProperty('uuid', line[1]); + if (existingPoint) { + return; + } + const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale); + const material = new THREE.ShaderMaterial({ + uniforms: { + uColor: { value: new THREE.Color(pointColour) }, // Blue color for the border + uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square + }, + vertexShader: ` + varying vec2 vUv; + + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); + } + `, + fragmentShader: ` + varying vec2 vUv; + uniform vec3 uColor; + uniform vec3 uInnerColor; + + void main() { + // Define the size of the white square as a proportion of the face + float borderThickness = 0.2; // Adjust this value for border thickness + if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && + vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) { + gl_FragColor = vec4(uInnerColor, 1.0); // White inner square + } else { + gl_FragColor = vec4(uColor, 1.0); // Blue border + } + } + `, + }); + const point = new THREE.Mesh(geometry, material); + point.name = "point"; + point.uuid = line[1]; + point.userData = { type: type, color: pointColour }; + point.position.set(line[0].x, line[0].y, line[0].z); + currentLayerPoint.current.push(point); + + floorPlanGroupPoint.current?.add(point); + }) + if (dragPointControls.current) { + dragPointControls.current!.objects = currentLayerPoint.current; + } + addLineToScene( + new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z), + new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z), + lineColour, + line, + floorPlanGroupLine + ) + lines.current.push(line); + + const zonesData = await getZonesApi(organization); + const highestLayer = Math.max( + 1, + lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), + zonesData.data.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) + ); + + setLayers(highestLayer); + + Layer2DVisibility(activeLayer, floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, currentLayerPoint, dragPointControls) + + loadWalls(lines, setWalls); + setUpdateScene(true); + } + }) + + return () => { + socket.off('Line:response:create'); + }; + }, [socket, activeLayer]) + + useEffect(() => { + if (!socket) return + const email = localStorage.getItem('email'); + const organization = (email!.split("@")[1]).split(".")[0]; + + socket.on('zone:response:updates', (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + + if (data.message === "zone created") { + const pointsArray: [number, number, number][] = data.data.points; + const vector3Array = pointsArray.map(([x, y, z]) => new THREE.Vector3(x, y, z)); + const newZones = [...zones, data.data]; + setZones(newZones); + const updatedZonePoints = [...zonePoints, ...vector3Array]; + setZonePoints(updatedZonePoints); + + const highestLayer = Math.max( + 1, + lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), + newZones.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) + ); + + setLayers(highestLayer); + setUpdateScene(true); + } + + if (data.message === "zone updated") { + const updatedZones = zones.map((zone: any) => + zone.zoneId === data.data.zoneId ? data.data : zone + ); + setZones(updatedZones); + setUpdateScene(true); + } + + + }) + + socket.on('zone:response:delete', (data: any) => { + if (socket.id === data.socketId) { + return + } + if (organization !== data.organization) { + return + } + if (data.message === "zone deleted") { + const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId); + setZones(updatedZones); + + const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === data.data.zoneId); + if (zoneIndex !== -1) { + const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4); + setZonePoints(updatedzonePoints); + } + + const highestLayer = Math.max( + 1, + lines.current.reduce((maxLayer: number, segment: any) => Math.max(maxLayer, segment.layer || 0), 0), + updatedZones.reduce((maxLayer: number, zone: any) => Math.max(maxLayer, zone.layer || 0), 0) + ); + + setLayers(highestLayer); + setUpdateScene(true); + } + }) + + return () => { + socket.off('zone:response:updates'); + socket.off('zone:response:updates'); + }; + }, [socket, zones, zonePoints]) + + return ( + <> + ) } \ No newline at end of file diff --git a/app/src/modules/scene/IntialLoad/loadInitialFloorItems.ts b/app/src/modules/scene/IntialLoad/loadInitialFloorItems.ts index 6633fe4..439cbc3 100644 --- a/app/src/modules/scene/IntialLoad/loadInitialFloorItems.ts +++ b/app/src/modules/scene/IntialLoad/loadInitialFloorItems.ts @@ -1,202 +1,202 @@ -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; -import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; -import gsap from 'gsap'; -import * as THREE from 'three'; -import * as CONSTANTS from '../../../types/world/worldConstants'; -import { toast } from 'react-toastify'; -import * as Types from "../../../types/world/worldTypes"; -import { getFloorItems } from '../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi'; -import { initializeDB, retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils'; -import { getCamera } from '../../../services/factoryBuilder/camera/getCameraApi'; - -async function loadInitialFloorItems( - itemsGroup: Types.RefGroup, - setFloorItems: Types.setFloorItemSetState -): Promise { - if (!itemsGroup.current) return; - let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; - const email = localStorage.getItem('email'); - const organization = (email!.split("@")[1]).split(".")[0]; - - const items = await getFloorItems(organization); - localStorage.setItem("FloorItems", JSON.stringify(items)); - await initializeDB(); - - if (items) { - const storedFloorItems: Types.FloorItems = items; - const loader = new GLTFLoader(); - const dracoLoader = new DRACOLoader(); - - dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); - loader.setDRACOLoader(dracoLoader); - - let modelsLoaded = 0; - const modelsToLoad = storedFloorItems.length; - - const camData = await getCamera(organization, localStorage.getItem('userId')!); - let storedPosition; - if (camData && camData.position) { - storedPosition = camData?.position; - } else { - storedPosition = new THREE.Vector3(0, 40, 30); - } - if (!storedPosition) return; - const cameraPosition = new THREE.Vector3(storedPosition.x, storedPosition.y, storedPosition.z); - - storedFloorItems.sort((a, b) => { - const aPosition = new THREE.Vector3(a.position[0], a.position[1], a.position[2]); - const bPosition = new THREE.Vector3(b.position[0], b.position[1], b.position[2]); - return cameraPosition.distanceTo(aPosition) - cameraPosition.distanceTo(bPosition); - }); - - for (const item of storedFloorItems) { - if (!item.modelfileID) return; - const itemPosition = new THREE.Vector3(item.position[0], item.position[1], item.position[2]); - let storedPosition; - if (localStorage.getItem("cameraPosition")) { - storedPosition = JSON.parse(localStorage.getItem("cameraPosition")!); - } else { - storedPosition = new THREE.Vector3(0, 40, 30); - } - - const cameraPosition = new THREE.Vector3(storedPosition.x, storedPosition.y, storedPosition.z); - - if (cameraPosition.distanceTo(itemPosition) < 50) { - await new Promise(async (resolve) => { - - // Check Three.js Cache - const cachedModel = THREE.Cache.get(item.modelfileID!); - if (cachedModel) { - // console.log(`[Cache] Fetching ${item.modelname}`); - processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems); - modelsLoaded++; - checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve); - return; - } - - // Check IndexedDB - const indexedDBModel = await retrieveGLTF(item.modelfileID!); - if (indexedDBModel) { - // console.log(`[IndexedDB] Fetching ${item.modelname}`); - const blobUrl = URL.createObjectURL(indexedDBModel); - loader.load( - blobUrl, - (gltf) => { - URL.revokeObjectURL(blobUrl); - THREE.Cache.remove(blobUrl); - THREE.Cache.add(item.modelfileID!, gltf); - processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems); - modelsLoaded++; - checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve); - }, - undefined, - (error) => { - toast.error(`[IndexedDB] Error loading ${item.modelname}:`); - URL.revokeObjectURL(blobUrl); - resolve(); - } - ); - return; - } - - // Fetch from Backend - // console.log(`[Backend] Fetching ${item.modelname}`); - const modelUrl = `${url_Backend_dwinzo}/api/v1/AssetFile/${item.modelfileID!}`; - loader.load( - modelUrl, - async (gltf) => { - const modelBlob = await fetch(modelUrl).then((res) => res.blob()); - await storeGLTF(item.modelfileID!, modelBlob); - THREE.Cache.add(item.modelfileID!, gltf); - processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems); - modelsLoaded++; - checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve); - }, - undefined, - (error) => { - toast.error(`[Backend] Error loading ${item.modelname}:`); - resolve(); - } - ); - }); - } else { - // console.log(`Item ${item.modelname} is not near`); - setFloorItems((prevItems) => [ - ...(prevItems || []), - { - modeluuid: item.modeluuid, - modelname: item.modelname, - position: item.position, - rotation: item.rotation, - modelfileID: item.modelfileID, - isLocked: item.isLocked, - isVisible: item.isVisible, - }, - ]); - modelsLoaded++; - checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, () => { }); - } - } - - // Dispose loader after all models - dracoLoader.dispose(); - } -} - - -function processLoadedModel( - gltf: any, - item: Types.FloorItemType, - itemsGroup: Types.RefGroup, - setFloorItems: Types.setFloorItemSetState -) { - const model = gltf; - model.uuid = item.modeluuid; - model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); - model.userData = { name: item.modelname, modelId: item.modelfileID }; - model.position.set(...item.position); - model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z); - - model.traverse((child: any) => { - if (child.isMesh) { - // Clone the material to ensure changes are independent - // child.material = child.material.clone(); - - child.castShadow = true; - child.receiveShadow = true; - } - }); - - - itemsGroup?.current?.add(model); - setFloorItems((prevItems) => [ - ...(prevItems || []), - { - modeluuid: item.modeluuid, - modelname: item.modelname, - position: item.position, - rotation: item.rotation, - modelfileID: item.modelfileID, - isLocked: item.isLocked, - isVisible: item.isVisible, - }, - ]); - - gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: 'power2.out' }); - gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out' }); -} - -function checkLoadingCompletion( - modelsLoaded: number, - modelsToLoad: number, - dracoLoader: DRACOLoader, - resolve: () => void -) { - if (modelsLoaded === modelsToLoad) { - toast.success("Models Loaded!"); - dracoLoader.dispose(); - } - resolve(); -} - +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; +import gsap from 'gsap'; +import * as THREE from 'three'; +import * as CONSTANTS from '../../../types/world/worldConstants'; +import { toast } from 'react-toastify'; +import * as Types from "../../../types/world/worldTypes"; +import { getFloorItems } from '../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi'; +import { initializeDB, retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils'; +import { getCamera } from '../../../services/factoryBuilder/camera/getCameraApi'; + +async function loadInitialFloorItems( + itemsGroup: Types.RefGroup, + setFloorItems: Types.setFloorItemSetState +): Promise { + if (!itemsGroup.current) return; + let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; + const email = localStorage.getItem('email'); + const organization = (email!.split("@")[1]).split(".")[0]; + + const items = await getFloorItems(organization); + localStorage.setItem("FloorItems", JSON.stringify(items)); + await initializeDB(); + + if (items) { + const storedFloorItems: Types.FloorItems = items; + const loader = new GLTFLoader(); + const dracoLoader = new DRACOLoader(); + + dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); + loader.setDRACOLoader(dracoLoader); + + let modelsLoaded = 0; + const modelsToLoad = storedFloorItems.length; + + const camData = await getCamera(organization, localStorage.getItem('userId')!); + let storedPosition; + if (camData && camData.position) { + storedPosition = camData?.position; + } else { + storedPosition = new THREE.Vector3(0, 40, 30); + } + if (!storedPosition) return; + const cameraPosition = new THREE.Vector3(storedPosition.x, storedPosition.y, storedPosition.z); + + storedFloorItems.sort((a, b) => { + const aPosition = new THREE.Vector3(a.position[0], a.position[1], a.position[2]); + const bPosition = new THREE.Vector3(b.position[0], b.position[1], b.position[2]); + return cameraPosition.distanceTo(aPosition) - cameraPosition.distanceTo(bPosition); + }); + + for (const item of storedFloorItems) { + if (!item.modelfileID) return; + const itemPosition = new THREE.Vector3(item.position[0], item.position[1], item.position[2]); + let storedPosition; + if (localStorage.getItem("cameraPosition")) { + storedPosition = JSON.parse(localStorage.getItem("cameraPosition")!); + } else { + storedPosition = new THREE.Vector3(0, 40, 30); + } + + const cameraPosition = new THREE.Vector3(storedPosition.x, storedPosition.y, storedPosition.z); + + if (cameraPosition.distanceTo(itemPosition) < 50) { + await new Promise(async (resolve) => { + + // Check Three.js Cache + const cachedModel = THREE.Cache.get(item.modelfileID!); + if (cachedModel) { + // console.log(`[Cache] Fetching ${item.modelname}`); + processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems); + modelsLoaded++; + checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve); + return; + } + + // Check IndexedDB + const indexedDBModel = await retrieveGLTF(item.modelfileID!); + if (indexedDBModel) { + // console.log(`[IndexedDB] Fetching ${item.modelname}`); + const blobUrl = URL.createObjectURL(indexedDBModel); + loader.load( + blobUrl, + (gltf) => { + URL.revokeObjectURL(blobUrl); + THREE.Cache.remove(blobUrl); + THREE.Cache.add(item.modelfileID!, gltf); + processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems); + modelsLoaded++; + checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve); + }, + undefined, + (error) => { + toast.error(`[IndexedDB] Error loading ${item.modelname}:`); + URL.revokeObjectURL(blobUrl); + resolve(); + } + ); + return; + } + + // Fetch from Backend + // console.log(`[Backend] Fetching ${item.modelname}`); + const modelUrl = `${url_Backend_dwinzo}/api/v1/AssetFile/${item.modelfileID!}`; + loader.load( + modelUrl, + async (gltf) => { + const modelBlob = await fetch(modelUrl).then((res) => res.blob()); + await storeGLTF(item.modelfileID!, modelBlob); + THREE.Cache.add(item.modelfileID!, gltf); + processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems); + modelsLoaded++; + checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve); + }, + undefined, + (error) => { + toast.error(`[Backend] Error loading ${item.modelname}:`); + resolve(); + } + ); + }); + } else { + // console.log(`Item ${item.modelname} is not near`); + setFloorItems((prevItems) => [ + ...(prevItems || []), + { + modeluuid: item.modeluuid, + modelname: item.modelname, + position: item.position, + rotation: item.rotation, + modelfileID: item.modelfileID, + isLocked: item.isLocked, + isVisible: item.isVisible, + }, + ]); + modelsLoaded++; + checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, () => { }); + } + } + + // Dispose loader after all models + dracoLoader.dispose(); + } +} + + +function processLoadedModel( + gltf: any, + item: Types.FloorItemType, + itemsGroup: Types.RefGroup, + setFloorItems: Types.setFloorItemSetState +) { + const model = gltf; + model.uuid = item.modeluuid; + model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); + model.userData = { name: item.modelname, modelId: item.modelfileID }; + model.position.set(...item.position); + model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z); + + model.traverse((child: any) => { + if (child.isMesh) { + // Clone the material to ensure changes are independent + // child.material = child.material.clone(); + + child.castShadow = true; + child.receiveShadow = true; + } + }); + + + itemsGroup?.current?.add(model); + setFloorItems((prevItems) => [ + ...(prevItems || []), + { + modeluuid: item.modeluuid, + modelname: item.modelname, + position: item.position, + rotation: item.rotation, + modelfileID: item.modelfileID, + isLocked: item.isLocked, + isVisible: item.isVisible, + }, + ]); + + gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: 'power2.out' }); + gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out' }); +} + +function checkLoadingCompletion( + modelsLoaded: number, + modelsToLoad: number, + dracoLoader: DRACOLoader, + resolve: () => void +) { + if (modelsLoaded === modelsToLoad) { + toast.success("Models Loaded!"); + dracoLoader.dispose(); + } + resolve(); +} + export default loadInitialFloorItems; \ No newline at end of file diff --git a/app/src/modules/scene/IntialLoad/loadInitialLine.ts b/app/src/modules/scene/IntialLoad/loadInitialLine.ts index f8c3132..231d5aa 100644 --- a/app/src/modules/scene/IntialLoad/loadInitialLine.ts +++ b/app/src/modules/scene/IntialLoad/loadInitialLine.ts @@ -1,30 +1,30 @@ -import addLineToScene from '../../builder/geomentries/lines/addLineToScene'; -import * as CONSTANTS from '../../../types/world/worldConstants'; -import * as Types from "../../../types/world/worldTypes"; - -function loadInitialLine( - floorPlanGroupLine: Types.RefGroup, - lines: Types.RefLines -): void { - - if (!floorPlanGroupLine.current) return - - ////////// Load the Lines initially if there are any ////////// - - floorPlanGroupLine.current.children = []; - lines.current.forEach((line) => { - let colour; - if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.wallName) { - colour = CONSTANTS.lineConfig.wallColor; - } else if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.floorName) { - colour = CONSTANTS.lineConfig.floorColor; - } else if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.aisleName) { - colour = CONSTANTS.lineConfig.aisleColor; - } - if (colour) { - addLineToScene(line[0][0], line[1][0], colour, line, floorPlanGroupLine); - } - }); -} - -export default loadInitialLine; +import addLineToScene from '../../builder/geomentries/lines/addLineToScene'; +import * as CONSTANTS from '../../../types/world/worldConstants'; +import * as Types from "../../../types/world/worldTypes"; + +function loadInitialLine( + floorPlanGroupLine: Types.RefGroup, + lines: Types.RefLines +): void { + + if (!floorPlanGroupLine.current) return + + ////////// Load the Lines initially if there are any ////////// + + floorPlanGroupLine.current.children = []; + lines.current.forEach((line) => { + let colour; + if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.wallName) { + colour = CONSTANTS.lineConfig.wallColor; + } else if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.floorName) { + colour = CONSTANTS.lineConfig.floorColor; + } else if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.aisleName) { + colour = CONSTANTS.lineConfig.aisleColor; + } + if (colour) { + addLineToScene(line[0][0], line[1][0], colour, line, floorPlanGroupLine); + } + }); +} + +export default loadInitialLine; diff --git a/app/src/modules/scene/IntialLoad/loadInitialPoint.ts b/app/src/modules/scene/IntialLoad/loadInitialPoint.ts index 7dfdf1d..f042427 100644 --- a/app/src/modules/scene/IntialLoad/loadInitialPoint.ts +++ b/app/src/modules/scene/IntialLoad/loadInitialPoint.ts @@ -1,87 +1,87 @@ -import * as THREE from 'three'; - -import * as CONSTANTS from '../../../types/world/worldConstants'; -import * as Types from "../../../types/world/worldTypes"; - -////////// Load the Boxes initially if there are any ////////// - -function loadInitialPoint( - lines: Types.RefLines, - floorPlanGroupPoint: Types.RefGroup, - currentLayerPoint: Types.RefMeshArray, - dragPointControls: Types.RefDragControl -): void { - - if (!floorPlanGroupPoint.current) return - - floorPlanGroupPoint.current.children = []; - currentLayerPoint.current = []; - lines.current.forEach((line) => { - const colour = getPointColor(line[0][3]); - line.forEach((pointData) => { - const [point, id] = pointData; - - /////////// Check if a box with this id already exists ////////// - - const existingBox = floorPlanGroupPoint.current?.getObjectByProperty('uuid', id); - if (existingBox) { - return; - } - - const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale); - const material = new THREE.ShaderMaterial({ - uniforms: { - uColor: { value: new THREE.Color(colour) }, // Blue color for the border - uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square - }, - vertexShader: ` - varying vec2 vUv; - - void main() { - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); - } - `, - fragmentShader: ` - varying vec2 vUv; - uniform vec3 uColor; - uniform vec3 uInnerColor; - - void main() { - // Define the size of the white square as a proportion of the face - float borderThickness = 0.2; // Adjust this value for border thickness - if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && - vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) { - gl_FragColor = vec4(uInnerColor, 1.0); // White inner square - } else { - gl_FragColor = vec4(uColor, 1.0); // Blue border - } - } - `, - }); - const box = new THREE.Mesh(geometry, material); - box.name = "point"; - box.uuid = id; - box.userData = { type: line[0][3], color: colour }; - box.position.set(point.x, point.y, point.z); - currentLayerPoint.current.push(box); - - floorPlanGroupPoint.current?.add(box); - }); - }); - - function getPointColor(lineType: string | undefined): string { - switch (lineType) { - case CONSTANTS.lineConfig.wallName: return CONSTANTS.pointConfig.wallOuterColor; - case CONSTANTS.lineConfig.floorName: return CONSTANTS.pointConfig.floorOuterColor; - case CONSTANTS.lineConfig.aisleName: return CONSTANTS.pointConfig.aisleOuterColor; - default: return CONSTANTS.pointConfig.defaultOuterColor; - } - } - - if (dragPointControls.current) { - dragPointControls.current!.objects = currentLayerPoint.current; - } -} - -export default loadInitialPoint; +import * as THREE from 'three'; + +import * as CONSTANTS from '../../../types/world/worldConstants'; +import * as Types from "../../../types/world/worldTypes"; + +////////// Load the Boxes initially if there are any ////////// + +function loadInitialPoint( + lines: Types.RefLines, + floorPlanGroupPoint: Types.RefGroup, + currentLayerPoint: Types.RefMeshArray, + dragPointControls: Types.RefDragControl +): void { + + if (!floorPlanGroupPoint.current) return + + floorPlanGroupPoint.current.children = []; + currentLayerPoint.current = []; + lines.current.forEach((line) => { + const colour = getPointColor(line[0][3]); + line.forEach((pointData) => { + const [point, id] = pointData; + + /////////// Check if a box with this id already exists ////////// + + const existingBox = floorPlanGroupPoint.current?.getObjectByProperty('uuid', id); + if (existingBox) { + return; + } + + const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale); + const material = new THREE.ShaderMaterial({ + uniforms: { + uColor: { value: new THREE.Color(colour) }, // Blue color for the border + uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square + }, + vertexShader: ` + varying vec2 vUv; + + void main() { + vUv = uv; + gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); + } + `, + fragmentShader: ` + varying vec2 vUv; + uniform vec3 uColor; + uniform vec3 uInnerColor; + + void main() { + // Define the size of the white square as a proportion of the face + float borderThickness = 0.2; // Adjust this value for border thickness + if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness && + vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) { + gl_FragColor = vec4(uInnerColor, 1.0); // White inner square + } else { + gl_FragColor = vec4(uColor, 1.0); // Blue border + } + } + `, + }); + const box = new THREE.Mesh(geometry, material); + box.name = "point"; + box.uuid = id; + box.userData = { type: line[0][3], color: colour }; + box.position.set(point.x, point.y, point.z); + currentLayerPoint.current.push(box); + + floorPlanGroupPoint.current?.add(box); + }); + }); + + function getPointColor(lineType: string | undefined): string { + switch (lineType) { + case CONSTANTS.lineConfig.wallName: return CONSTANTS.pointConfig.wallOuterColor; + case CONSTANTS.lineConfig.floorName: return CONSTANTS.pointConfig.floorOuterColor; + case CONSTANTS.lineConfig.aisleName: return CONSTANTS.pointConfig.aisleOuterColor; + default: return CONSTANTS.pointConfig.defaultOuterColor; + } + } + + if (dragPointControls.current) { + dragPointControls.current!.objects = currentLayerPoint.current; + } +} + +export default loadInitialPoint; diff --git a/app/src/modules/scene/IntialLoad/loadInitialWallItems.ts b/app/src/modules/scene/IntialLoad/loadInitialWallItems.ts index 34273af..c5184bb 100644 --- a/app/src/modules/scene/IntialLoad/loadInitialWallItems.ts +++ b/app/src/modules/scene/IntialLoad/loadInitialWallItems.ts @@ -1,54 +1,54 @@ -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; - -import * as Types from "../../../types/world/worldTypes"; -import { getWallItems } from '../../../services/factoryBuilder/assest/wallAsset/getWallItemsApi'; - -////////// Load the Wall Items's intially of there is any ////////// - -async function loadInitialWallItems( - setWallItems: Types.setWallItemSetState, - AssetConfigurations: Types.AssetConfigurations -): Promise { - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - const items = await getWallItems(organization); - - localStorage.setItem("WallItems", JSON.stringify(items)); - if (items.length > 0) { - const storedWallItems: Types.wallItems = items; - - const loadedWallItems = await Promise.all(storedWallItems.map(async (item) => { - const loader = new GLTFLoader(); - return new Promise((resolve) => { - loader.load(AssetConfigurations[item.modelname!].modelUrl, (gltf) => { - const model = gltf.scene; - model.uuid = item.modeluuid!; - - model.children[0].children.forEach((child: any) => { - if (child.name !== "CSG_REF") { - child.castShadow = true; - child.receiveShadow = true; - } - }); - - resolve({ - type: item.type, - model: model, - modelname: item.modelname, - scale: item.scale, - csgscale: item.csgscale, - csgposition: item.csgposition, - position: item.position, - quaternion: item.quaternion, - }); - }); - }); - })); - - setWallItems(loadedWallItems); - } -} - -export default loadInitialWallItems; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; + +import * as Types from "../../../types/world/worldTypes"; +import { getWallItems } from '../../../services/factoryBuilder/assest/wallAsset/getWallItemsApi'; + +////////// Load the Wall Items's intially of there is any ////////// + +async function loadInitialWallItems( + setWallItems: Types.setWallItemSetState, + AssetConfigurations: Types.AssetConfigurations +): Promise { + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + const items = await getWallItems(organization); + + localStorage.setItem("WallItems", JSON.stringify(items)); + if (items.length > 0) { + const storedWallItems: Types.wallItems = items; + + const loadedWallItems = await Promise.all(storedWallItems.map(async (item) => { + const loader = new GLTFLoader(); + return new Promise((resolve) => { + loader.load(AssetConfigurations[item.modelname!].modelUrl, (gltf) => { + const model = gltf.scene; + model.uuid = item.modeluuid!; + + model.children[0].children.forEach((child: any) => { + if (child.name !== "CSG_REF") { + child.castShadow = true; + child.receiveShadow = true; + } + }); + + resolve({ + type: item.type, + model: model, + modelname: item.modelname, + scale: item.scale, + csgscale: item.csgscale, + csgposition: item.csgposition, + position: item.position, + quaternion: item.quaternion, + }); + }); + }); + })); + + setWallItems(loadedWallItems); + } +} + +export default loadInitialWallItems; diff --git a/app/src/modules/scene/camera/camMode.tsx b/app/src/modules/scene/camera/camMode.tsx index dbab5e7..ba1aa0f 100644 --- a/app/src/modules/scene/camera/camMode.tsx +++ b/app/src/modules/scene/camera/camMode.tsx @@ -1,89 +1,89 @@ -import { useFrame, useThree } from '@react-three/fiber'; -import React, { useEffect, useState } from 'react'; -import * as CONSTANTS from '../../../types/world/worldConstants'; -import { useCamMode, useToggleView } from '../../../store/store'; -import { useKeyboardControls } from '@react-three/drei'; -import switchToThirdPerson from './switchToThirdPerson'; -import switchToFirstPerson from './switchToFirstPerson'; - -const CamMode: React.FC = () => { - const { camMode, setCamMode } = useCamMode(); - const [, get] = useKeyboardControls() - const [isTransitioning, setIsTransitioning] = useState(false); - const state: any = useThree(); - const { toggleView } = useToggleView(); - - useEffect(() => { - const handlePointerLockChange = async () => { - if (document.pointerLockElement && !toggleView) { - // console.log('Pointer is locked'); - } else { - // console.log('Pointer is unlocked'); - if (camMode === "FirstPerson" && !toggleView) { - setCamMode("ThirdPerson"); - await switchToThirdPerson(state.controls, state.camera); - } - } - }; - - document.addEventListener('pointerlockchange', handlePointerLockChange); - - return () => { - document.removeEventListener('pointerlockchange', handlePointerLockChange); - }; - }, [camMode, toggleView, setCamMode, state.controls, state.camera]); - - useEffect(() => { - const handleKeyPress = async (event: any) => { - if (!state.controls) return; - - if (event.key === "/" && !isTransitioning && !toggleView) { - setIsTransitioning(true); - state.controls.mouseButtons.left = CONSTANTS.controlsTransition.leftMouse; - state.controls.mouseButtons.right = CONSTANTS.controlsTransition.rightMouse; - state.controls.mouseButtons.wheel = CONSTANTS.controlsTransition.wheelMouse; - state.controls.mouseButtons.middle = CONSTANTS.controlsTransition.middleMouse; - - if (camMode === 'ThirdPerson') { - setCamMode("FirstPerson"); - await switchToFirstPerson(state.controls, state.camera); - } else if (camMode === "FirstPerson") { - setCamMode("ThirdPerson"); - await switchToThirdPerson(state.controls, state.camera); - } - - setIsTransitioning(false); - } - }; - - window.addEventListener("keydown", handleKeyPress); - return () => { - window.removeEventListener("keydown", handleKeyPress); - }; - }, [camMode, isTransitioning, toggleView, state.controls, state.camera, setCamMode]); - - useFrame(() => { - const { forward, backward, left, right } = get(); - if (!state.controls) return - if (!state.controls || camMode === "ThirdPerson" || !document.pointerLockElement) return; - - if (forward) { - state.controls.forward(CONSTANTS.firstPersonControls.forwardSpeed, true) - } - if (backward) { - state.controls.forward(CONSTANTS.firstPersonControls.backwardSpeed, true) - } - if (left) { - state.controls.truck(CONSTANTS.firstPersonControls.leftSpeed, 0, true) - } - if (right) { - state.controls.truck(CONSTANTS.firstPersonControls.rightSpeed, 0, true) - } - }); - - return ( - <> - ); -}; - +import { useFrame, useThree } from '@react-three/fiber'; +import React, { useEffect, useState } from 'react'; +import * as CONSTANTS from '../../../types/world/worldConstants'; +import { useCamMode, useToggleView } from '../../../store/store'; +import { useKeyboardControls } from '@react-three/drei'; +import switchToThirdPerson from './switchToThirdPerson'; +import switchToFirstPerson from './switchToFirstPerson'; + +const CamMode: React.FC = () => { + const { camMode, setCamMode } = useCamMode(); + const [, get] = useKeyboardControls() + const [isTransitioning, setIsTransitioning] = useState(false); + const state: any = useThree(); + const { toggleView } = useToggleView(); + + useEffect(() => { + const handlePointerLockChange = async () => { + if (document.pointerLockElement && !toggleView) { + // console.log('Pointer is locked'); + } else { + // console.log('Pointer is unlocked'); + if (camMode === "FirstPerson" && !toggleView) { + setCamMode("ThirdPerson"); + await switchToThirdPerson(state.controls, state.camera); + } + } + }; + + document.addEventListener('pointerlockchange', handlePointerLockChange); + + return () => { + document.removeEventListener('pointerlockchange', handlePointerLockChange); + }; + }, [camMode, toggleView, setCamMode, state.controls, state.camera]); + + useEffect(() => { + const handleKeyPress = async (event: any) => { + if (!state.controls) return; + + if (event.key === "/" && !isTransitioning && !toggleView) { + setIsTransitioning(true); + state.controls.mouseButtons.left = CONSTANTS.controlsTransition.leftMouse; + state.controls.mouseButtons.right = CONSTANTS.controlsTransition.rightMouse; + state.controls.mouseButtons.wheel = CONSTANTS.controlsTransition.wheelMouse; + state.controls.mouseButtons.middle = CONSTANTS.controlsTransition.middleMouse; + + if (camMode === 'ThirdPerson') { + setCamMode("FirstPerson"); + await switchToFirstPerson(state.controls, state.camera); + } else if (camMode === "FirstPerson") { + setCamMode("ThirdPerson"); + await switchToThirdPerson(state.controls, state.camera); + } + + setIsTransitioning(false); + } + }; + + window.addEventListener("keydown", handleKeyPress); + return () => { + window.removeEventListener("keydown", handleKeyPress); + }; + }, [camMode, isTransitioning, toggleView, state.controls, state.camera, setCamMode]); + + useFrame(() => { + const { forward, backward, left, right } = get(); + if (!state.controls) return + if (!state.controls || camMode === "ThirdPerson" || !document.pointerLockElement) return; + + if (forward) { + state.controls.forward(CONSTANTS.firstPersonControls.forwardSpeed, true) + } + if (backward) { + state.controls.forward(CONSTANTS.firstPersonControls.backwardSpeed, true) + } + if (left) { + state.controls.truck(CONSTANTS.firstPersonControls.leftSpeed, 0, true) + } + if (right) { + state.controls.truck(CONSTANTS.firstPersonControls.rightSpeed, 0, true) + } + }); + + return ( + <> + ); +}; + export default CamMode; \ No newline at end of file diff --git a/app/src/modules/scene/camera/switchToFirstPerson.ts b/app/src/modules/scene/camera/switchToFirstPerson.ts index 6746220..a5371c4 100644 --- a/app/src/modules/scene/camera/switchToFirstPerson.ts +++ b/app/src/modules/scene/camera/switchToFirstPerson.ts @@ -1,25 +1,25 @@ -import * as THREE from 'three'; -import * as CONSTANTS from '../../../types/world/worldConstants'; - -export default async function switchToFirstPerson( - controls: any, - camera: any -) { - if (!controls) return; - - const cameraDirection = new THREE.Vector3(); - camera.getWorldDirection(cameraDirection); - cameraDirection.normalize(); - - await controls.setPosition(camera.position.x, 2, camera.position.z, true); - controls.setTarget(camera.position.x, 2, camera.position.z, true); - controls.mouseButtons.left = CONSTANTS.firstPersonControls.leftMouse; - controls.lockPointer(); - - controls.azimuthRotateSpeed = CONSTANTS.firstPersonControls.azimuthRotateSpeed; - controls.polarRotateSpeed = CONSTANTS.firstPersonControls.polarRotateSpeed; - controls.truckSpeed = CONSTANTS.firstPersonControls.truckSpeed; - controls.minDistance = CONSTANTS.firstPersonControls.minDistance; - controls.maxDistance = CONSTANTS.firstPersonControls.maxDistance; - controls.maxPolarAngle = CONSTANTS.firstPersonControls.maxPolarAngle; +import * as THREE from 'three'; +import * as CONSTANTS from '../../../types/world/worldConstants'; + +export default async function switchToFirstPerson( + controls: any, + camera: any +) { + if (!controls) return; + + const cameraDirection = new THREE.Vector3(); + camera.getWorldDirection(cameraDirection); + cameraDirection.normalize(); + + await controls.setPosition(camera.position.x, 2, camera.position.z, true); + controls.setTarget(camera.position.x, 2, camera.position.z, true); + controls.mouseButtons.left = CONSTANTS.firstPersonControls.leftMouse; + controls.lockPointer(); + + controls.azimuthRotateSpeed = CONSTANTS.firstPersonControls.azimuthRotateSpeed; + controls.polarRotateSpeed = CONSTANTS.firstPersonControls.polarRotateSpeed; + controls.truckSpeed = CONSTANTS.firstPersonControls.truckSpeed; + controls.minDistance = CONSTANTS.firstPersonControls.minDistance; + controls.maxDistance = CONSTANTS.firstPersonControls.maxDistance; + controls.maxPolarAngle = CONSTANTS.firstPersonControls.maxPolarAngle; } \ No newline at end of file diff --git a/app/src/modules/scene/camera/switchToThirdPerson.ts b/app/src/modules/scene/camera/switchToThirdPerson.ts index f43bc79..1e59749 100644 --- a/app/src/modules/scene/camera/switchToThirdPerson.ts +++ b/app/src/modules/scene/camera/switchToThirdPerson.ts @@ -1,29 +1,29 @@ -import * as THREE from 'three'; -import * as CONSTANTS from '../../../types/world/worldConstants'; - -export default async function switchToThirdPerson( - controls: any, - camera: any -) { - if (!controls) return; - controls.mouseButtons.left = CONSTANTS.thirdPersonControls.leftMouse; - controls.mouseButtons.right = CONSTANTS.thirdPersonControls.rightMouse; - controls.mouseButtons.middle = CONSTANTS.thirdPersonControls.middleMouse; - controls.mouseButtons.wheel = CONSTANTS.thirdPersonControls.wheelMouse; - controls.unlockPointer(); - - const cameraDirection = new THREE.Vector3(); - camera.getWorldDirection(cameraDirection); - const targetOffset = cameraDirection.multiplyScalar(CONSTANTS.thirdPersonControls.targetOffset); - const targetPosition = new THREE.Vector3(camera.position.x, camera.position.y, camera.position.z).add(targetOffset); - - controls.setPosition(camera.position.x, CONSTANTS.thirdPersonControls.cameraHeight, camera.position.z, true); - controls.setTarget(targetPosition.x, 0, targetPosition.z, true); - - controls.azimuthRotateSpeed = CONSTANTS.thirdPersonControls.azimuthRotateSpeed; - controls.polarRotateSpeed = CONSTANTS.thirdPersonControls.polarRotateSpeed; - controls.truckSpeed = CONSTANTS.thirdPersonControls.truckSpeed; - controls.minDistance = CONSTANTS.threeDimension.minDistance; - controls.maxDistance = CONSTANTS.thirdPersonControls.maxDistance; - controls.maxPolarAngle = CONSTANTS.thirdPersonControls.maxPolarAngle; +import * as THREE from 'three'; +import * as CONSTANTS from '../../../types/world/worldConstants'; + +export default async function switchToThirdPerson( + controls: any, + camera: any +) { + if (!controls) return; + controls.mouseButtons.left = CONSTANTS.thirdPersonControls.leftMouse; + controls.mouseButtons.right = CONSTANTS.thirdPersonControls.rightMouse; + controls.mouseButtons.middle = CONSTANTS.thirdPersonControls.middleMouse; + controls.mouseButtons.wheel = CONSTANTS.thirdPersonControls.wheelMouse; + controls.unlockPointer(); + + const cameraDirection = new THREE.Vector3(); + camera.getWorldDirection(cameraDirection); + const targetOffset = cameraDirection.multiplyScalar(CONSTANTS.thirdPersonControls.targetOffset); + const targetPosition = new THREE.Vector3(camera.position.x, camera.position.y, camera.position.z).add(targetOffset); + + controls.setPosition(camera.position.x, CONSTANTS.thirdPersonControls.cameraHeight, camera.position.z, true); + controls.setTarget(targetPosition.x, 0, targetPosition.z, true); + + controls.azimuthRotateSpeed = CONSTANTS.thirdPersonControls.azimuthRotateSpeed; + controls.polarRotateSpeed = CONSTANTS.thirdPersonControls.polarRotateSpeed; + controls.truckSpeed = CONSTANTS.thirdPersonControls.truckSpeed; + controls.minDistance = CONSTANTS.threeDimension.minDistance; + controls.maxDistance = CONSTANTS.thirdPersonControls.maxDistance; + controls.maxPolarAngle = CONSTANTS.thirdPersonControls.maxPolarAngle; } \ No newline at end of file diff --git a/app/src/modules/scene/camera/switchView.tsx b/app/src/modules/scene/camera/switchView.tsx index 1241a30..2472031 100644 --- a/app/src/modules/scene/camera/switchView.tsx +++ b/app/src/modules/scene/camera/switchView.tsx @@ -1,70 +1,70 @@ -import * as THREE from "three"; -import { useEffect, useRef } from "react"; -import { useToggleView } from "../../../store/store"; -import { useThree } from "@react-three/fiber"; -import { getCamera } from "../../../services/factoryBuilder/camera/getCameraApi"; -import * as CONSTANTS from '../../../types/world/worldConstants'; - -export default function SwitchView() { - const { toggleView } = useToggleView(); - const state: any = useThree(); - const { set } = useThree(); - const perspectiveCamera = useRef(null); - const orthoCamera = useRef(null); - orthoCamera.current = new THREE.OrthographicCamera(-window.innerWidth / 2, window.innerWidth / 2, window.innerHeight / 2, -window.innerHeight / 2, 0.01, 1000); - perspectiveCamera.current = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 1000); - - useEffect(() => { - if (!perspectiveCamera.current || !orthoCamera.current) return; - if (toggleView) { - orthoCamera.current.zoom = 10; - orthoCamera.current.position.set(...CONSTANTS.twoDimension.defaultPosition); - orthoCamera.current.lookAt(new THREE.Vector3(...CONSTANTS.twoDimension.defaultTarget)); - orthoCamera.current.updateProjectionMatrix(); - set({ camera: orthoCamera.current }); - orthoCamera.current.updateProjectionMatrix(); - } else if (!toggleView) { - perspectiveCamera.current.position.set(...CONSTANTS.threeDimension.defaultPosition); - perspectiveCamera.current.lookAt(new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget)); - set({ camera: perspectiveCamera.current }); - } - }, [toggleView, set]); - - useEffect(() => { - if (toggleView && state.controls) { - state.controls.mouseButtons.left = CONSTANTS.twoDimension.leftMouse; - state.controls.mouseButtons.right = CONSTANTS.twoDimension.rightMouse; - } else { - try { - const email = localStorage.getItem('email'); - const organization = (email!.split("@")[1]).split(".")[0]; - getCamera(organization, localStorage.getItem('userId')!).then((data) => { - if (data && data.position && data.target) { - state.controls?.setPosition(data.position.x, data.position.y, data.position.z); - state.controls?.setTarget(data.target.x, data.target.y, data.target.z); - localStorage.setItem("cameraPosition", JSON.stringify(data.position)); - localStorage.setItem("controlTarget", JSON.stringify(data.target)); - } else { - state.controls?.setPosition(...CONSTANTS.threeDimension.defaultPosition); - state.controls?.setTarget(...CONSTANTS.threeDimension.defaultTarget); - localStorage.setItem("cameraPosition", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition))); - localStorage.setItem("controlTarget", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget))); - } - }); - } catch (error) { - console.error("Failed to retrieve camera position or target:", error); - state.controls?.setPosition(...CONSTANTS.threeDimension.defaultPosition); - state.controls?.setTarget(...CONSTANTS.threeDimension.defaultTarget); - } - - if (state.controls) { - state.controls.mouseButtons.left = CONSTANTS.threeDimension.leftMouse; - state.controls.mouseButtons.right = CONSTANTS.threeDimension.rightMouse; - } - } - }, [toggleView, state.controls]); - - return ( - <> - ); +import * as THREE from "three"; +import { useEffect, useRef } from "react"; +import { useToggleView } from "../../../store/store"; +import { useThree } from "@react-three/fiber"; +import { getCamera } from "../../../services/factoryBuilder/camera/getCameraApi"; +import * as CONSTANTS from '../../../types/world/worldConstants'; + +export default function SwitchView() { + const { toggleView } = useToggleView(); + const state: any = useThree(); + const { set } = useThree(); + const perspectiveCamera = useRef(null); + const orthoCamera = useRef(null); + orthoCamera.current = new THREE.OrthographicCamera(-window.innerWidth / 2, window.innerWidth / 2, window.innerHeight / 2, -window.innerHeight / 2, 0.01, 1000); + perspectiveCamera.current = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 1000); + + useEffect(() => { + if (!perspectiveCamera.current || !orthoCamera.current) return; + if (toggleView) { + orthoCamera.current.zoom = 10; + orthoCamera.current.position.set(...CONSTANTS.twoDimension.defaultPosition); + orthoCamera.current.lookAt(new THREE.Vector3(...CONSTANTS.twoDimension.defaultTarget)); + orthoCamera.current.updateProjectionMatrix(); + set({ camera: orthoCamera.current }); + orthoCamera.current.updateProjectionMatrix(); + } else if (!toggleView) { + perspectiveCamera.current.position.set(...CONSTANTS.threeDimension.defaultPosition); + perspectiveCamera.current.lookAt(new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget)); + set({ camera: perspectiveCamera.current }); + } + }, [toggleView, set]); + + useEffect(() => { + if (toggleView && state.controls) { + state.controls.mouseButtons.left = CONSTANTS.twoDimension.leftMouse; + state.controls.mouseButtons.right = CONSTANTS.twoDimension.rightMouse; + } else { + try { + const email = localStorage.getItem('email'); + const organization = (email!.split("@")[1]).split(".")[0]; + getCamera(organization, localStorage.getItem('userId')!).then((data) => { + if (data && data.position && data.target) { + state.controls?.setPosition(data.position.x, data.position.y, data.position.z); + state.controls?.setTarget(data.target.x, data.target.y, data.target.z); + localStorage.setItem("cameraPosition", JSON.stringify(data.position)); + localStorage.setItem("controlTarget", JSON.stringify(data.target)); + } else { + state.controls?.setPosition(...CONSTANTS.threeDimension.defaultPosition); + state.controls?.setTarget(...CONSTANTS.threeDimension.defaultTarget); + localStorage.setItem("cameraPosition", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition))); + localStorage.setItem("controlTarget", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget))); + } + }); + } catch (error) { + console.error("Failed to retrieve camera position or target:", error); + state.controls?.setPosition(...CONSTANTS.threeDimension.defaultPosition); + state.controls?.setTarget(...CONSTANTS.threeDimension.defaultTarget); + } + + if (state.controls) { + state.controls.mouseButtons.left = CONSTANTS.threeDimension.leftMouse; + state.controls.mouseButtons.right = CONSTANTS.threeDimension.rightMouse; + } + } + }, [toggleView, state.controls]); + + return ( + <> + ); } \ No newline at end of file diff --git a/app/src/modules/scene/camera/updateCameraPosition.ts b/app/src/modules/scene/camera/updateCameraPosition.ts index 4b76b1a..6967494 100644 --- a/app/src/modules/scene/camera/updateCameraPosition.ts +++ b/app/src/modules/scene/camera/updateCameraPosition.ts @@ -1,26 +1,26 @@ -import { Socket } from "socket.io-client"; -import * as THREE from 'three'; - -export default function updateCamPosition( - controls: any, - socket: Socket, - position: THREE.Vector3, - rotation: THREE.Euler -) { - if (!controls.current) return; - const target = controls.current.getTarget(new THREE.Vector3()); - const email = localStorage.getItem("email"); - const organization = email!.split("@")[1].split(".")[0]; - - const camData = { - organization: organization, - userId: localStorage.getItem("userId")!, - position: position, - target: new THREE.Vector3(target.x, 0, target.z), - rotation: new THREE.Vector3(rotation.x, rotation.y, rotation.z), - socketId: socket.id, - }; - socket.emit("v1:Camera:set", camData); - localStorage.setItem("cameraPosition", JSON.stringify(position)); - localStorage.setItem("controlTarget", JSON.stringify(new THREE.Vector3(target.x, 0, target.z))); +import { Socket } from "socket.io-client"; +import * as THREE from 'three'; + +export default function updateCamPosition( + controls: any, + socket: Socket, + position: THREE.Vector3, + rotation: THREE.Euler +) { + if (!controls.current) return; + const target = controls.current.getTarget(new THREE.Vector3()); + const email = localStorage.getItem("email"); + const organization = email!.split("@")[1].split(".")[0]; + + const camData = { + organization: organization, + userId: localStorage.getItem("userId")!, + position: position, + target: new THREE.Vector3(target.x, 0, target.z), + rotation: new THREE.Vector3(rotation.x, rotation.y, rotation.z), + socketId: socket.id, + }; + socket.emit("v1:Camera:set", camData); + localStorage.setItem("cameraPosition", JSON.stringify(position)); + localStorage.setItem("controlTarget", JSON.stringify(new THREE.Vector3(target.x, 0, target.z))); } \ No newline at end of file diff --git a/app/src/modules/scene/controls/controls.tsx b/app/src/modules/scene/controls/controls.tsx index 367098e..0e7581f 100644 --- a/app/src/modules/scene/controls/controls.tsx +++ b/app/src/modules/scene/controls/controls.tsx @@ -1,136 +1,136 @@ -import { CameraControls } from "@react-three/drei"; -import { useRef, useEffect } from "react"; -import { useThree } from "@react-three/fiber"; -import * as THREE from "three"; -import * as CONSTANTS from '../../../types/world/worldConstants'; - -import { useSocketStore, useToggleView, useResetCamera } from "../../../store/store"; -import { getCamera } from "../../../services/factoryBuilder/camera/getCameraApi"; -import updateCamPosition from "../camera/updateCameraPosition"; -import CamMode from "../camera/camMode"; -import SwitchView from "../camera/switchView"; - -export default function Controls() { - const controlsRef = useRef(null); - - const { toggleView } = useToggleView(); - const { resetCamera, setResetCamera } = useResetCamera(); - const { socket } = useSocketStore(); - const state = useThree(); - - useEffect(() => { - if (controlsRef.current) { - (controlsRef.current as any).mouseButtons.left = CONSTANTS.thirdPersonControls.leftMouse; - (controlsRef.current as any).mouseButtons.right = CONSTANTS.thirdPersonControls.rightMouse; - } - const email = localStorage.getItem("email"); - const organization = email!.split("@")[1].split(".")[0]; - getCamera(organization, localStorage.getItem("userId")!).then((data) => { - if (data && data.position && data.target) { - controlsRef.current?.setPosition(data.position.x, data.position.y, data.position.z); - controlsRef.current?.setTarget(data.target.x, data.target.y, data.target.z); - } else { - controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition); - controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget); - } - }) - .catch((error) => console.error("Failed to fetch camera data:", error)); - }, []); - - useEffect(() => { - if (resetCamera) { - controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition); - controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget); - controlsRef.current?.rotateAzimuthTo(CONSTANTS.threeDimension.defaultAzimuth); - - localStorage.setItem("cameraPosition", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition))); - localStorage.setItem("controlTarget", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget))); - - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - const camData = { - organization: organization, - userId: localStorage.getItem('userId')!, - position: new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition), - target: new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget), - rotation: new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation), - socketId: socket.id - }; - socket.emit('v1:Camera:set', camData) - - setResetCamera(false); - } - }, [resetCamera]); - - useEffect(() => { - controlsRef.current?.setBoundary(new THREE.Box3(new THREE.Vector3(...CONSTANTS.threeDimension.boundaryBottom), new THREE.Vector3(...CONSTANTS.threeDimension.boundaryTop))); - // state.scene.add(new THREE.Box3Helper(new THREE.Box3(new THREE.Vector3(...CONSTANTS.threeDimension.boundaryBottom), new THREE.Vector3(...CONSTANTS.threeDimension.boundaryTop)), 0xffff00)); - let hasInteracted = false; - let intervalId: NodeJS.Timeout | null = null; - - const handleRest = () => { - if (hasInteracted && controlsRef.current && state.camera.position && !toggleView) { - const position = state.camera.position; - if (position.x === 0 && position.y === 0 && position.z === 0) return; - updateCamPosition(controlsRef, socket, position, state.camera.rotation); - stopInterval(); - } - }; - - const startInterval = () => { - hasInteracted = true; - if (!intervalId) { - intervalId = setInterval(() => { - if (controlsRef.current && !toggleView) { - handleRest(); - } - }, CONSTANTS.camPositionUpdateInterval); - } - }; - - const stopInterval = () => { - if (intervalId) { - clearInterval(intervalId); - intervalId = null; - } - }; - - const controls = controlsRef.current; - if (controls) { - controls.addEventListener("sleep", handleRest); - controls.addEventListener("control", startInterval); - controls.addEventListener("controlend", stopInterval); - } - - return () => { - if (controls) { - controls.removeEventListener("sleep", handleRest); - controls.removeEventListener("control", startInterval); - controls.removeEventListener("controlend", stopInterval); - } - stopInterval(); - }; - }, [toggleView, state, socket]); - - return ( - <> - - - - - - ); +import { CameraControls } from "@react-three/drei"; +import { useRef, useEffect } from "react"; +import { useThree } from "@react-three/fiber"; +import * as THREE from "three"; +import * as CONSTANTS from '../../../types/world/worldConstants'; + +import { useSocketStore, useToggleView, useResetCamera } from "../../../store/store"; +import { getCamera } from "../../../services/factoryBuilder/camera/getCameraApi"; +import updateCamPosition from "../camera/updateCameraPosition"; +import CamMode from "../camera/camMode"; +import SwitchView from "../camera/switchView"; + +export default function Controls() { + const controlsRef = useRef(null); + + const { toggleView } = useToggleView(); + const { resetCamera, setResetCamera } = useResetCamera(); + const { socket } = useSocketStore(); + const state = useThree(); + + useEffect(() => { + if (controlsRef.current) { + (controlsRef.current as any).mouseButtons.left = CONSTANTS.thirdPersonControls.leftMouse; + (controlsRef.current as any).mouseButtons.right = CONSTANTS.thirdPersonControls.rightMouse; + } + const email = localStorage.getItem("email"); + const organization = email!.split("@")[1].split(".")[0]; + getCamera(organization, localStorage.getItem("userId")!).then((data) => { + if (data && data.position && data.target) { + controlsRef.current?.setPosition(data.position.x, data.position.y, data.position.z); + controlsRef.current?.setTarget(data.target.x, data.target.y, data.target.z); + } else { + controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition); + controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget); + } + }) + .catch((error) => console.error("Failed to fetch camera data:", error)); + }, []); + + useEffect(() => { + if (resetCamera) { + controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition); + controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget); + controlsRef.current?.rotateAzimuthTo(CONSTANTS.threeDimension.defaultAzimuth); + + localStorage.setItem("cameraPosition", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition))); + localStorage.setItem("controlTarget", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget))); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + const camData = { + organization: organization, + userId: localStorage.getItem('userId')!, + position: new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition), + target: new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget), + rotation: new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation), + socketId: socket.id + }; + socket.emit('v1:Camera:set', camData) + + setResetCamera(false); + } + }, [resetCamera]); + + useEffect(() => { + controlsRef.current?.setBoundary(new THREE.Box3(new THREE.Vector3(...CONSTANTS.threeDimension.boundaryBottom), new THREE.Vector3(...CONSTANTS.threeDimension.boundaryTop))); + // state.scene.add(new THREE.Box3Helper(new THREE.Box3(new THREE.Vector3(...CONSTANTS.threeDimension.boundaryBottom), new THREE.Vector3(...CONSTANTS.threeDimension.boundaryTop)), 0xffff00)); + let hasInteracted = false; + let intervalId: NodeJS.Timeout | null = null; + + const handleRest = () => { + if (hasInteracted && controlsRef.current && state.camera.position && !toggleView) { + const position = state.camera.position; + if (position.x === 0 && position.y === 0 && position.z === 0) return; + updateCamPosition(controlsRef, socket, position, state.camera.rotation); + stopInterval(); + } + }; + + const startInterval = () => { + hasInteracted = true; + if (!intervalId) { + intervalId = setInterval(() => { + if (controlsRef.current && !toggleView) { + handleRest(); + } + }, CONSTANTS.camPositionUpdateInterval); + } + }; + + const stopInterval = () => { + if (intervalId) { + clearInterval(intervalId); + intervalId = null; + } + }; + + const controls = controlsRef.current; + if (controls) { + controls.addEventListener("sleep", handleRest); + controls.addEventListener("control", startInterval); + controls.addEventListener("controlend", stopInterval); + } + + return () => { + if (controls) { + controls.removeEventListener("sleep", handleRest); + controls.removeEventListener("control", startInterval); + controls.removeEventListener("controlend", stopInterval); + } + stopInterval(); + }; + }, [toggleView, state, socket]); + + return ( + <> + + + + + + ); } \ No newline at end of file diff --git a/app/src/modules/scene/controls/selection/boundingBoxHelper.tsx b/app/src/modules/scene/controls/selection/boundingBoxHelper.tsx index e725a7f..ebc3761 100644 --- a/app/src/modules/scene/controls/selection/boundingBoxHelper.tsx +++ b/app/src/modules/scene/controls/selection/boundingBoxHelper.tsx @@ -1,62 +1,62 @@ -import { Line } from "@react-three/drei"; -import { useMemo } from "react"; -import * as THREE from "three"; -import { useSelectedAssets } from "../../../../store/store"; - -const BoundingBox = ({ boundingBoxRef }: any) => { - const { selectedAssets } = useSelectedAssets(); - - const { points, boxProps } = useMemo(() => { - if (selectedAssets.length === 0) return { points: [], boxProps: {} }; - - const box = new THREE.Box3(); - selectedAssets.forEach((obj: any) => box.expandByObject(obj.clone())); - - const size = new THREE.Vector3(); - box.getSize(size); - const center = new THREE.Vector3(); - box.getCenter(center); - - const halfSize = size.clone().multiplyScalar(0.5); - const min = center.clone().sub(halfSize); - const max = center.clone().add(halfSize); - - const points: any = [ - [min.x, min.y, min.z], [max.x, min.y, min.z], - [max.x, min.y, min.z], [max.x, max.y, min.z], - [max.x, max.y, min.z], [min.x, max.y, min.z], - [min.x, max.y, min.z], [min.x, min.y, min.z], - - [min.x, min.y, max.z], [max.x, min.y, max.z], - [max.x, min.y, max.z], [max.x, max.y, max.z], - [max.x, max.y, max.z], [min.x, max.y, max.z], - [min.x, max.y, max.z], [min.x, min.y, max.z], - - [min.x, min.y, min.z], [min.x, min.y, max.z], - [max.x, min.y, min.z], [max.x, min.y, max.z], - [max.x, max.y, min.z], [max.x, max.y, max.z], - [min.x, max.y, min.z], [min.x, max.y, max.z], - ]; - - return { - points, - boxProps: { position: center.toArray(), args: size.toArray() } - }; - }, [selectedAssets]); - - return ( - <> - {points.length > 0 && ( - <> - - - - - - - )} - - ); -}; - -export default BoundingBox; +import { Line } from "@react-three/drei"; +import { useMemo } from "react"; +import * as THREE from "three"; +import { useSelectedAssets } from "../../../../store/store"; + +const BoundingBox = ({ boundingBoxRef }: any) => { + const { selectedAssets } = useSelectedAssets(); + + const { points, boxProps } = useMemo(() => { + if (selectedAssets.length === 0) return { points: [], boxProps: {} }; + + const box = new THREE.Box3(); + selectedAssets.forEach((obj: any) => box.expandByObject(obj.clone())); + + const size = new THREE.Vector3(); + box.getSize(size); + const center = new THREE.Vector3(); + box.getCenter(center); + + const halfSize = size.clone().multiplyScalar(0.5); + const min = center.clone().sub(halfSize); + const max = center.clone().add(halfSize); + + const points: any = [ + [min.x, min.y, min.z], [max.x, min.y, min.z], + [max.x, min.y, min.z], [max.x, max.y, min.z], + [max.x, max.y, min.z], [min.x, max.y, min.z], + [min.x, max.y, min.z], [min.x, min.y, min.z], + + [min.x, min.y, max.z], [max.x, min.y, max.z], + [max.x, min.y, max.z], [max.x, max.y, max.z], + [max.x, max.y, max.z], [min.x, max.y, max.z], + [min.x, max.y, max.z], [min.x, min.y, max.z], + + [min.x, min.y, min.z], [min.x, min.y, max.z], + [max.x, min.y, min.z], [max.x, min.y, max.z], + [max.x, max.y, min.z], [max.x, max.y, max.z], + [min.x, max.y, min.z], [min.x, max.y, max.z], + ]; + + return { + points, + boxProps: { position: center.toArray(), args: size.toArray() } + }; + }, [selectedAssets]); + + return ( + <> + {points.length > 0 && ( + <> + + + + + + + )} + + ); +}; + +export default BoundingBox; diff --git a/app/src/modules/scene/controls/selection/copyPasteControls.tsx b/app/src/modules/scene/controls/selection/copyPasteControls.tsx index 3eafd93..3082462 100644 --- a/app/src/modules/scene/controls/selection/copyPasteControls.tsx +++ b/app/src/modules/scene/controls/selection/copyPasteControls.tsx @@ -1,209 +1,209 @@ -import * as THREE from "three"; -import { useEffect, useMemo } from "react"; -import { useFrame, useThree } from "@react-three/fiber"; -import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; -import { toast } from "react-toastify"; -// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; -import * as Types from "../../../../types/world/worldTypes"; - -const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, selectionGroup, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => { - const { camera, controls, gl, scene, pointer, raycaster } = useThree(); - const { toggleView } = useToggleView(); - const { selectedAssets, setSelectedAssets } = useSelectedAssets(); - const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); - const { floorItems, setFloorItems } = useFloorItems(); - const { socket } = useSocketStore() - - useEffect(() => { - if (!camera || !scene || toggleView) return; - const canvasElement = gl.domElement; - canvasElement.tabIndex = 0; - - let isMoving = false; - - const onPointerDown = () => { - isMoving = false; - }; - - const onPointerMove = () => { - isMoving = true; - }; - - const onPointerUp = (event: PointerEvent) => { - if (!isMoving && pastedObjects.length > 0 && event.button === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { - event.preventDefault(); - addPastedObjects(); - } - }; - - const onKeyDown = (event: KeyboardEvent) => { - if (event.ctrlKey && event.key.toLowerCase() === "c" && movedObjects.length === 0 && rotatedObjects.length === 0) { - copySelection(); - } - if (event.ctrlKey && event.key.toLowerCase() === "v" && copiedObjects.length > 0 && pastedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { - pasteCopiedObjects(); - } - }; - - if (!toggleView) { - canvasElement.addEventListener("pointerdown", onPointerDown); - canvasElement.addEventListener("pointermove", onPointerMove); - canvasElement.addEventListener("pointerup", onPointerUp); - canvasElement.addEventListener("keydown", onKeyDown); - } - - return () => { - canvasElement.removeEventListener("pointerdown", onPointerDown); - canvasElement.removeEventListener("pointermove", onPointerMove); - canvasElement.removeEventListener("pointerup", onPointerUp); - canvasElement.removeEventListener("keydown", onKeyDown); - }; - - }, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, movedObjects, socket, floorItems, rotatedObjects]); - - useFrame(() => { - if (pastedObjects.length > 0) { - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - if (point) { - const position = new THREE.Vector3(); - if (boundingBoxRef.current) { - boundingBoxRef.current?.getWorldPosition(position) - selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); - } else { - const box = new THREE.Box3(); - pastedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone())); - const center = new THREE.Vector3(); - box.getCenter(center); - selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z)); - } - } - } - }); - - const copySelection = () => { - if (selectedAssets.length > 0) { - const newClones = selectedAssets.map((asset: any) => { - const clone = asset.clone(); - clone.position.copy(asset.position); - return clone; - }); - setCopiedObjects(newClones); - toast.info("Objects copied!"); - } - }; - - const pasteCopiedObjects = () => { - if (copiedObjects.length > 0 && pastedObjects.length === 0) { - const newClones = copiedObjects.map((obj: THREE.Object3D) => { - const clone = obj.clone(); - clone.position.copy(obj.position); - return clone; - }); - selectionGroup.current.add(...newClones); - setpastedObjects([...newClones]); - setSelectedAssets([...newClones]); - - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - - if (point) { - const position = new THREE.Vector3(); - if (boundingBoxRef.current) { - boundingBoxRef.current?.getWorldPosition(position) - selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); - } else { - const box = new THREE.Box3(); - newClones.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone())); - const center = new THREE.Vector3(); - box.getCenter(center); - selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z)); - } - } - } - }; - - const addPastedObjects = () => { - if (pastedObjects.length === 0) return; - pastedObjects.forEach(async (obj: THREE.Object3D) => { - const worldPosition = new THREE.Vector3(); - obj.getWorldPosition(worldPosition); - obj.position.copy(worldPosition); - - if (itemsGroupRef.current) { - - const newFloorItem: Types.FloorItemType = { - modeluuid: obj.uuid, - modelname: obj.userData.name, - modelfileID: obj.userData.modelId, - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, - isLocked: false, - isVisible: true - }; - - setFloorItems((prevItems: Types.FloorItems) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); - - const email = localStorage.getItem("email"); - const organization = email ? email.split("@")[1].split(".")[0] : "default"; - - //REST - - // await setFloorItemApi( - // organization, - // obj.uuid, - // obj.userData.name, - // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, - // obj.userData.modelId, - // false, - // true, - // ); - - //SOCKET - - const data = { - organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, - modelfileID: newFloorItem.modelfileID, - position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, - isLocked: false, - isVisible: true, - socketId: socket.id, - }; - - socket.emit("v1:FloorItems:set", data); - - itemsGroupRef.current.add(obj); - } - }); - - toast.success("Object added!"); - clearSelection(); - }; - - const clearSelection = () => { - selectionGroup.current.children = []; - selectionGroup.current.position.set(0, 0, 0); - selectionGroup.current.rotation.set(0, 0, 0); - setMovedObjects([]); - setpastedObjects([]); - setDuplicatedObjects([]); - setRotatedObjects([]); - setSelectedAssets([]); - } - - return ( - <> - ); -}; - +import * as THREE from "three"; +import { useEffect, useMemo } from "react"; +import { useFrame, useThree } from "@react-three/fiber"; +import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; +import { toast } from "react-toastify"; +// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; +import * as Types from "../../../../types/world/worldTypes"; + +const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, selectionGroup, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => { + const { camera, controls, gl, scene, pointer, raycaster } = useThree(); + const { toggleView } = useToggleView(); + const { selectedAssets, setSelectedAssets } = useSelectedAssets(); + const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); + const { floorItems, setFloorItems } = useFloorItems(); + const { socket } = useSocketStore() + + useEffect(() => { + if (!camera || !scene || toggleView) return; + const canvasElement = gl.domElement; + canvasElement.tabIndex = 0; + + let isMoving = false; + + const onPointerDown = () => { + isMoving = false; + }; + + const onPointerMove = () => { + isMoving = true; + }; + + const onPointerUp = (event: PointerEvent) => { + if (!isMoving && pastedObjects.length > 0 && event.button === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { + event.preventDefault(); + addPastedObjects(); + } + }; + + const onKeyDown = (event: KeyboardEvent) => { + if (event.ctrlKey && event.key.toLowerCase() === "c" && movedObjects.length === 0 && rotatedObjects.length === 0) { + copySelection(); + } + if (event.ctrlKey && event.key.toLowerCase() === "v" && copiedObjects.length > 0 && pastedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { + pasteCopiedObjects(); + } + }; + + if (!toggleView) { + canvasElement.addEventListener("pointerdown", onPointerDown); + canvasElement.addEventListener("pointermove", onPointerMove); + canvasElement.addEventListener("pointerup", onPointerUp); + canvasElement.addEventListener("keydown", onKeyDown); + } + + return () => { + canvasElement.removeEventListener("pointerdown", onPointerDown); + canvasElement.removeEventListener("pointermove", onPointerMove); + canvasElement.removeEventListener("pointerup", onPointerUp); + canvasElement.removeEventListener("keydown", onKeyDown); + }; + + }, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, movedObjects, socket, floorItems, rotatedObjects]); + + useFrame(() => { + if (pastedObjects.length > 0) { + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + if (point) { + const position = new THREE.Vector3(); + if (boundingBoxRef.current) { + boundingBoxRef.current?.getWorldPosition(position) + selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); + } else { + const box = new THREE.Box3(); + pastedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone())); + const center = new THREE.Vector3(); + box.getCenter(center); + selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z)); + } + } + } + }); + + const copySelection = () => { + if (selectedAssets.length > 0) { + const newClones = selectedAssets.map((asset: any) => { + const clone = asset.clone(); + clone.position.copy(asset.position); + return clone; + }); + setCopiedObjects(newClones); + toast.info("Objects copied!"); + } + }; + + const pasteCopiedObjects = () => { + if (copiedObjects.length > 0 && pastedObjects.length === 0) { + const newClones = copiedObjects.map((obj: THREE.Object3D) => { + const clone = obj.clone(); + clone.position.copy(obj.position); + return clone; + }); + selectionGroup.current.add(...newClones); + setpastedObjects([...newClones]); + setSelectedAssets([...newClones]); + + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + + if (point) { + const position = new THREE.Vector3(); + if (boundingBoxRef.current) { + boundingBoxRef.current?.getWorldPosition(position) + selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); + } else { + const box = new THREE.Box3(); + newClones.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone())); + const center = new THREE.Vector3(); + box.getCenter(center); + selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z)); + } + } + } + }; + + const addPastedObjects = () => { + if (pastedObjects.length === 0) return; + pastedObjects.forEach(async (obj: THREE.Object3D) => { + const worldPosition = new THREE.Vector3(); + obj.getWorldPosition(worldPosition); + obj.position.copy(worldPosition); + + if (itemsGroupRef.current) { + + const newFloorItem: Types.FloorItemType = { + modeluuid: obj.uuid, + modelname: obj.userData.name, + modelfileID: obj.userData.modelId, + position: [worldPosition.x, worldPosition.y, worldPosition.z], + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, + isLocked: false, + isVisible: true + }; + + setFloorItems((prevItems: Types.FloorItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + const email = localStorage.getItem("email"); + const organization = email ? email.split("@")[1].split(".")[0] : "default"; + + //REST + + // await setFloorItemApi( + // organization, + // obj.uuid, + // obj.userData.name, + // [worldPosition.x, worldPosition.y, worldPosition.z], + // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, + // obj.userData.modelId, + // false, + // true, + // ); + + //SOCKET + + const data = { + organization, + modeluuid: newFloorItem.modeluuid, + modelname: newFloorItem.modelname, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id, + }; + + socket.emit("v1:FloorItems:set", data); + + itemsGroupRef.current.add(obj); + } + }); + + toast.success("Object added!"); + clearSelection(); + }; + + const clearSelection = () => { + selectionGroup.current.children = []; + selectionGroup.current.position.set(0, 0, 0); + selectionGroup.current.rotation.set(0, 0, 0); + setMovedObjects([]); + setpastedObjects([]); + setDuplicatedObjects([]); + setRotatedObjects([]); + setSelectedAssets([]); + } + + return ( + <> + ); +}; + export default CopyPasteControls; \ No newline at end of file diff --git a/app/src/modules/scene/controls/selection/duplicationControls.tsx b/app/src/modules/scene/controls/selection/duplicationControls.tsx index a38b6cd..cbe561a 100644 --- a/app/src/modules/scene/controls/selection/duplicationControls.tsx +++ b/app/src/modules/scene/controls/selection/duplicationControls.tsx @@ -1,190 +1,190 @@ -import * as THREE from "three"; -import { useEffect, useMemo } from "react"; -import { useFrame, useThree } from "@react-three/fiber"; -import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; -import { toast } from "react-toastify"; -// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; -import * as Types from "../../../../types/world/worldTypes"; - -const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedObjects, setpastedObjects, selectionGroup, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => { - const { camera, controls, gl, scene, pointer, raycaster } = useThree(); - const { toggleView } = useToggleView(); - const { selectedAssets, setSelectedAssets } = useSelectedAssets(); - const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); - const { floorItems, setFloorItems } = useFloorItems(); - const { socket } = useSocketStore(); - - - useEffect(() => { - if (!camera || !scene || toggleView) return; - const canvasElement = gl.domElement; - canvasElement.tabIndex = 0; - - let isMoving = false; - - const onPointerDown = () => { - isMoving = false; - }; - - const onPointerMove = () => { - isMoving = true; - }; - - const onPointerUp = (event: PointerEvent) => { - if (!isMoving && duplicatedObjects.length > 0 && event.button === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { - event.preventDefault(); - addDuplicatedAssets(); - } - }; - - const onKeyDown = (event: KeyboardEvent) => { - if (event.key.toLowerCase() === "d") { - event.preventDefault(); - if (event.ctrlKey && event.key.toLowerCase() === "d" && selectedAssets.length > 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { - duplicateSelection(); - } - } - }; - - if (!toggleView) { - canvasElement.addEventListener("pointerdown", onPointerDown); - canvasElement.addEventListener("pointermove", onPointerMove); - canvasElement.addEventListener("pointerup", onPointerUp); - canvasElement.addEventListener("keydown", onKeyDown); - } - - return () => { - canvasElement.removeEventListener("pointerdown", onPointerDown); - canvasElement.removeEventListener("pointermove", onPointerMove); - canvasElement.removeEventListener("pointerup", onPointerUp); - canvasElement.removeEventListener("keydown", onKeyDown); - }; - - }, [camera, controls, scene, toggleView, selectedAssets, duplicatedObjects, movedObjects, socket, floorItems, rotatedObjects]); - - useFrame(() => { - if (duplicatedObjects.length > 0) { - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - if (point) { - const position = new THREE.Vector3(); - if (boundingBoxRef.current) { - boundingBoxRef.current?.getWorldPosition(position) - selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); - } else { - const box = new THREE.Box3(); - duplicatedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone())); - const center = new THREE.Vector3(); - box.getCenter(center); - selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z)); - } - } - } - }); - - const duplicateSelection = () => { - if (selectedAssets.length > 0 && duplicatedObjects.length === 0) { - const newClones = selectedAssets.map((asset: any) => { - const clone = asset.clone(); - clone.position.copy(asset.position); - return clone; - }); - - selectionGroup.current.add(...newClones); - setDuplicatedObjects(newClones); - - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - - if (point) { - const position = new THREE.Vector3(); - boundingBoxRef.current?.getWorldPosition(position) - selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); - } - } - }; - - const addDuplicatedAssets = () => { - if (duplicatedObjects.length === 0) return; - duplicatedObjects.forEach(async (obj: THREE.Object3D) => { - const worldPosition = new THREE.Vector3(); - obj.getWorldPosition(worldPosition); - obj.position.copy(worldPosition); - - if (itemsGroupRef.current) { - - const newFloorItem: Types.FloorItemType = { - modeluuid: obj.uuid, - modelname: obj.userData.name, - modelfileID: obj.userData.modelId, - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, - isLocked: false, - isVisible: true - }; - - setFloorItems((prevItems: Types.FloorItems) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); - - const email = localStorage.getItem("email"); - const organization = email ? email.split("@")[1].split(".")[0] : "default"; - - //REST - - // await setFloorItemApi( - // organization, - // obj.uuid, - // obj.userData.name, - // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, - // obj.userData.modelId, - // false, - // true, - // ); - - //SOCKET - - const data = { - organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, - modelfileID: newFloorItem.modelfileID, - position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, - isLocked: false, - isVisible: true, - socketId: socket.id, - }; - - socket.emit("v1:FloorItems:set", data); - - itemsGroupRef.current.add(obj); - } - }); - - toast.success("Object duplicated!"); - clearSelection(); - } - - const clearSelection = () => { - selectionGroup.current.children = []; - selectionGroup.current.position.set(0, 0, 0); - selectionGroup.current.rotation.set(0, 0, 0); - setMovedObjects([]); - setpastedObjects([]); - setDuplicatedObjects([]); - setRotatedObjects([]); - setSelectedAssets([]); - } - - return ( - <> - ); -}; - +import * as THREE from "three"; +import { useEffect, useMemo } from "react"; +import { useFrame, useThree } from "@react-three/fiber"; +import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; +import { toast } from "react-toastify"; +// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; +import * as Types from "../../../../types/world/worldTypes"; + +const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedObjects, setpastedObjects, selectionGroup, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => { + const { camera, controls, gl, scene, pointer, raycaster } = useThree(); + const { toggleView } = useToggleView(); + const { selectedAssets, setSelectedAssets } = useSelectedAssets(); + const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); + const { floorItems, setFloorItems } = useFloorItems(); + const { socket } = useSocketStore(); + + + useEffect(() => { + if (!camera || !scene || toggleView) return; + const canvasElement = gl.domElement; + canvasElement.tabIndex = 0; + + let isMoving = false; + + const onPointerDown = () => { + isMoving = false; + }; + + const onPointerMove = () => { + isMoving = true; + }; + + const onPointerUp = (event: PointerEvent) => { + if (!isMoving && duplicatedObjects.length > 0 && event.button === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { + event.preventDefault(); + addDuplicatedAssets(); + } + }; + + const onKeyDown = (event: KeyboardEvent) => { + if (event.key.toLowerCase() === "d") { + event.preventDefault(); + if (event.ctrlKey && event.key.toLowerCase() === "d" && selectedAssets.length > 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { + duplicateSelection(); + } + } + }; + + if (!toggleView) { + canvasElement.addEventListener("pointerdown", onPointerDown); + canvasElement.addEventListener("pointermove", onPointerMove); + canvasElement.addEventListener("pointerup", onPointerUp); + canvasElement.addEventListener("keydown", onKeyDown); + } + + return () => { + canvasElement.removeEventListener("pointerdown", onPointerDown); + canvasElement.removeEventListener("pointermove", onPointerMove); + canvasElement.removeEventListener("pointerup", onPointerUp); + canvasElement.removeEventListener("keydown", onKeyDown); + }; + + }, [camera, controls, scene, toggleView, selectedAssets, duplicatedObjects, movedObjects, socket, floorItems, rotatedObjects]); + + useFrame(() => { + if (duplicatedObjects.length > 0) { + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + if (point) { + const position = new THREE.Vector3(); + if (boundingBoxRef.current) { + boundingBoxRef.current?.getWorldPosition(position) + selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); + } else { + const box = new THREE.Box3(); + duplicatedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone())); + const center = new THREE.Vector3(); + box.getCenter(center); + selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z)); + } + } + } + }); + + const duplicateSelection = () => { + if (selectedAssets.length > 0 && duplicatedObjects.length === 0) { + const newClones = selectedAssets.map((asset: any) => { + const clone = asset.clone(); + clone.position.copy(asset.position); + return clone; + }); + + selectionGroup.current.add(...newClones); + setDuplicatedObjects(newClones); + + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + + if (point) { + const position = new THREE.Vector3(); + boundingBoxRef.current?.getWorldPosition(position) + selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); + } + } + }; + + const addDuplicatedAssets = () => { + if (duplicatedObjects.length === 0) return; + duplicatedObjects.forEach(async (obj: THREE.Object3D) => { + const worldPosition = new THREE.Vector3(); + obj.getWorldPosition(worldPosition); + obj.position.copy(worldPosition); + + if (itemsGroupRef.current) { + + const newFloorItem: Types.FloorItemType = { + modeluuid: obj.uuid, + modelname: obj.userData.name, + modelfileID: obj.userData.modelId, + position: [worldPosition.x, worldPosition.y, worldPosition.z], + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, + isLocked: false, + isVisible: true + }; + + setFloorItems((prevItems: Types.FloorItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + const email = localStorage.getItem("email"); + const organization = email ? email.split("@")[1].split(".")[0] : "default"; + + //REST + + // await setFloorItemApi( + // organization, + // obj.uuid, + // obj.userData.name, + // [worldPosition.x, worldPosition.y, worldPosition.z], + // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, + // obj.userData.modelId, + // false, + // true, + // ); + + //SOCKET + + const data = { + organization, + modeluuid: newFloorItem.modeluuid, + modelname: newFloorItem.modelname, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id, + }; + + socket.emit("v1:FloorItems:set", data); + + itemsGroupRef.current.add(obj); + } + }); + + toast.success("Object duplicated!"); + clearSelection(); + } + + const clearSelection = () => { + selectionGroup.current.children = []; + selectionGroup.current.position.set(0, 0, 0); + selectionGroup.current.rotation.set(0, 0, 0); + setMovedObjects([]); + setpastedObjects([]); + setDuplicatedObjects([]); + setRotatedObjects([]); + setSelectedAssets([]); + } + + return ( + <> + ); +}; + export default DuplicationControls; \ No newline at end of file diff --git a/app/src/modules/scene/controls/selection/moveControls.tsx b/app/src/modules/scene/controls/selection/moveControls.tsx index 5f7eb11..bbdb3e1 100644 --- a/app/src/modules/scene/controls/selection/moveControls.tsx +++ b/app/src/modules/scene/controls/selection/moveControls.tsx @@ -1,239 +1,239 @@ -import * as THREE from "three"; -import { useEffect, useMemo, useRef, useState } from "react"; -import { useFrame, useThree } from "@react-three/fiber"; -import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; -// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; -import { toast } from "react-toastify"; -import * as Types from "../../../../types/world/worldTypes"; - -function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) { - const { camera, controls, gl, scene, pointer, raycaster } = useThree(); - const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); - - const { toggleView } = useToggleView(); - const { selectedAssets, setSelectedAssets } = useSelectedAssets(); - const { floorItems, setFloorItems } = useFloorItems(); - const { socket } = useSocketStore(); - const itemsData = useRef([]); - - useEffect(() => { - if (!camera || !scene || toggleView || !itemsGroupRef.current) return; - - const canvasElement = gl.domElement; - canvasElement.tabIndex = 0; - - let isMoving = false; - - const onPointerDown = () => { - isMoving = false; - }; - - const onPointerMove = () => { - isMoving = true; - }; - - const onPointerUp = (event: PointerEvent) => { - if (!isMoving && movedObjects.length > 0 && event.button === 0) { - event.preventDefault(); - placeMovedAssets(); - } - if (!isMoving && movedObjects.length > 0 && event.button === 2) { - event.preventDefault(); - - clearSelection(); - movedObjects.forEach((asset: any) => { - if (itemsGroupRef.current) { - itemsGroupRef.current.attach(asset); - } - }); - - setFloorItems([...floorItems, ...itemsData.current]); - - setMovedObjects([]); - itemsData.current = []; - } - }; - - const onKeyDown = (event: KeyboardEvent) => { - if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0) return; - if (event.key.toLowerCase() === "g") { - if (selectedAssets.length > 0) { - moveAssets(); - itemsData.current = floorItems.filter((item: { modeluuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); - } - } - if (event.key.toLowerCase() === "escape") { - event.preventDefault(); - - clearSelection(); - movedObjects.forEach((asset: any) => { - if (itemsGroupRef.current) { - itemsGroupRef.current.attach(asset); - } - }); - - setFloorItems([...floorItems, ...itemsData.current]); - - setMovedObjects([]); - itemsData.current = []; - } - }; - - if (!toggleView) { - canvasElement.addEventListener("pointerdown", onPointerDown); - canvasElement.addEventListener("pointermove", onPointerMove); - canvasElement.addEventListener("pointerup", onPointerUp); - canvasElement.addEventListener("keydown", onKeyDown); - } - - return () => { - canvasElement.removeEventListener("pointerdown", onPointerDown); - canvasElement.removeEventListener("pointermove", onPointerMove); - canvasElement.removeEventListener("pointerup", onPointerUp); - canvasElement.removeEventListener("keydown", onKeyDown); - }; - }, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects]); - - const gridSize = 0.25; - const moveSpeed = 0.25; - const isGridSnap = false; - - useFrame(() => { - if (movedObjects.length > 0) { - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - - if (point) { - let targetX = point.x; - let targetZ = point.z; - - if (isGridSnap) { - targetX = Math.round(point.x / gridSize) * gridSize; - targetZ = Math.round(point.z / gridSize) * gridSize; - } - - const position = new THREE.Vector3(); - if (boundingBoxRef.current) { - boundingBoxRef.current.getWorldPosition(position); - selectionGroup.current.position.lerp( - new THREE.Vector3( - targetX - (position.x - selectionGroup.current.position.x), - selectionGroup.current.position.y, - targetZ - (position.z - selectionGroup.current.position.z) - ), - moveSpeed - ); - } else { - const box = new THREE.Box3(); - movedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj)); - const center = new THREE.Vector3(); - box.getCenter(center); - - selectionGroup.current.position.lerp( - new THREE.Vector3( - targetX - (center.x - selectionGroup.current.position.x), - selectionGroup.current.position.y, - targetZ - (center.z - selectionGroup.current.position.z) - ), - moveSpeed - ); - } - } - } - }); - - - const moveAssets = () => { - const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); - setFloorItems(updatedItems); - setMovedObjects(selectedAssets); - selectedAssets.forEach((asset: any) => { selectionGroup.current.attach(asset); }); - } - - const placeMovedAssets = () => { - if (movedObjects.length === 0) return; - - movedObjects.forEach(async (obj: THREE.Object3D) => { - const worldPosition = new THREE.Vector3(); - obj.getWorldPosition(worldPosition); - - selectionGroup.current.remove(obj); - obj.position.copy(worldPosition); - - if (itemsGroupRef.current) { - - const newFloorItem: Types.FloorItemType = { - modeluuid: obj.uuid, - modelname: obj.userData.name, - modelfileID: obj.userData.modelId, - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, - isLocked: false, - isVisible: true - }; - - setFloorItems((prevItems: Types.FloorItems) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); - - const email = localStorage.getItem("email"); - const organization = email ? email.split("@")[1].split(".")[0] : "default"; - - //REST - - // await setFloorItemApi( - // organization, - // obj.uuid, - // obj.userData.name, - // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, - // obj.userData.modelId, - // false, - // true, - // ); - - //SOCKET - - const data = { - organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, - modelfileID: newFloorItem.modelfileID, - position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, - isLocked: false, - isVisible: true, - socketId: socket.id, - }; - - socket.emit("v1:FloorItems:set", data); - - itemsGroupRef.current.add(obj); - } - }); - toast.success("Object moved!"); - - itemsData.current = []; - clearSelection(); - } - - const clearSelection = () => { - selectionGroup.current.children = []; - selectionGroup.current.position.set(0, 0, 0); - selectionGroup.current.rotation.set(0, 0, 0); - setpastedObjects([]); - setDuplicatedObjects([]); - setMovedObjects([]); - setRotatedObjects([]); - setSelectedAssets([]); - } - - return ( - <> - ) -} - +import * as THREE from "three"; +import { useEffect, useMemo, useRef, useState } from "react"; +import { useFrame, useThree } from "@react-three/fiber"; +import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; +// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; +import { toast } from "react-toastify"; +import * as Types from "../../../../types/world/worldTypes"; + +function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) { + const { camera, controls, gl, scene, pointer, raycaster } = useThree(); + const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); + + const { toggleView } = useToggleView(); + const { selectedAssets, setSelectedAssets } = useSelectedAssets(); + const { floorItems, setFloorItems } = useFloorItems(); + const { socket } = useSocketStore(); + const itemsData = useRef([]); + + useEffect(() => { + if (!camera || !scene || toggleView || !itemsGroupRef.current) return; + + const canvasElement = gl.domElement; + canvasElement.tabIndex = 0; + + let isMoving = false; + + const onPointerDown = () => { + isMoving = false; + }; + + const onPointerMove = () => { + isMoving = true; + }; + + const onPointerUp = (event: PointerEvent) => { + if (!isMoving && movedObjects.length > 0 && event.button === 0) { + event.preventDefault(); + placeMovedAssets(); + } + if (!isMoving && movedObjects.length > 0 && event.button === 2) { + event.preventDefault(); + + clearSelection(); + movedObjects.forEach((asset: any) => { + if (itemsGroupRef.current) { + itemsGroupRef.current.attach(asset); + } + }); + + setFloorItems([...floorItems, ...itemsData.current]); + + setMovedObjects([]); + itemsData.current = []; + } + }; + + const onKeyDown = (event: KeyboardEvent) => { + if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0) return; + if (event.key.toLowerCase() === "g") { + if (selectedAssets.length > 0) { + moveAssets(); + itemsData.current = floorItems.filter((item: { modeluuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); + } + } + if (event.key.toLowerCase() === "escape") { + event.preventDefault(); + + clearSelection(); + movedObjects.forEach((asset: any) => { + if (itemsGroupRef.current) { + itemsGroupRef.current.attach(asset); + } + }); + + setFloorItems([...floorItems, ...itemsData.current]); + + setMovedObjects([]); + itemsData.current = []; + } + }; + + if (!toggleView) { + canvasElement.addEventListener("pointerdown", onPointerDown); + canvasElement.addEventListener("pointermove", onPointerMove); + canvasElement.addEventListener("pointerup", onPointerUp); + canvasElement.addEventListener("keydown", onKeyDown); + } + + return () => { + canvasElement.removeEventListener("pointerdown", onPointerDown); + canvasElement.removeEventListener("pointermove", onPointerMove); + canvasElement.removeEventListener("pointerup", onPointerUp); + canvasElement.removeEventListener("keydown", onKeyDown); + }; + }, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects]); + + const gridSize = 0.25; + const moveSpeed = 0.25; + const isGridSnap = false; + + useFrame(() => { + if (movedObjects.length > 0) { + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + + if (point) { + let targetX = point.x; + let targetZ = point.z; + + if (isGridSnap) { + targetX = Math.round(point.x / gridSize) * gridSize; + targetZ = Math.round(point.z / gridSize) * gridSize; + } + + const position = new THREE.Vector3(); + if (boundingBoxRef.current) { + boundingBoxRef.current.getWorldPosition(position); + selectionGroup.current.position.lerp( + new THREE.Vector3( + targetX - (position.x - selectionGroup.current.position.x), + selectionGroup.current.position.y, + targetZ - (position.z - selectionGroup.current.position.z) + ), + moveSpeed + ); + } else { + const box = new THREE.Box3(); + movedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj)); + const center = new THREE.Vector3(); + box.getCenter(center); + + selectionGroup.current.position.lerp( + new THREE.Vector3( + targetX - (center.x - selectionGroup.current.position.x), + selectionGroup.current.position.y, + targetZ - (center.z - selectionGroup.current.position.z) + ), + moveSpeed + ); + } + } + } + }); + + + const moveAssets = () => { + const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); + setFloorItems(updatedItems); + setMovedObjects(selectedAssets); + selectedAssets.forEach((asset: any) => { selectionGroup.current.attach(asset); }); + } + + const placeMovedAssets = () => { + if (movedObjects.length === 0) return; + + movedObjects.forEach(async (obj: THREE.Object3D) => { + const worldPosition = new THREE.Vector3(); + obj.getWorldPosition(worldPosition); + + selectionGroup.current.remove(obj); + obj.position.copy(worldPosition); + + if (itemsGroupRef.current) { + + const newFloorItem: Types.FloorItemType = { + modeluuid: obj.uuid, + modelname: obj.userData.name, + modelfileID: obj.userData.modelId, + position: [worldPosition.x, worldPosition.y, worldPosition.z], + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, + isLocked: false, + isVisible: true + }; + + setFloorItems((prevItems: Types.FloorItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + const email = localStorage.getItem("email"); + const organization = email ? email.split("@")[1].split(".")[0] : "default"; + + //REST + + // await setFloorItemApi( + // organization, + // obj.uuid, + // obj.userData.name, + // [worldPosition.x, worldPosition.y, worldPosition.z], + // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, + // obj.userData.modelId, + // false, + // true, + // ); + + //SOCKET + + const data = { + organization, + modeluuid: newFloorItem.modeluuid, + modelname: newFloorItem.modelname, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id, + }; + + socket.emit("v1:FloorItems:set", data); + + itemsGroupRef.current.add(obj); + } + }); + toast.success("Object moved!"); + + itemsData.current = []; + clearSelection(); + } + + const clearSelection = () => { + selectionGroup.current.children = []; + selectionGroup.current.position.set(0, 0, 0); + selectionGroup.current.rotation.set(0, 0, 0); + setpastedObjects([]); + setDuplicatedObjects([]); + setMovedObjects([]); + setRotatedObjects([]); + setSelectedAssets([]); + } + + return ( + <> + ) +} + export default MoveControls \ No newline at end of file diff --git a/app/src/modules/scene/controls/selection/rotateControls.tsx b/app/src/modules/scene/controls/selection/rotateControls.tsx index b28f921..6e65839 100644 --- a/app/src/modules/scene/controls/selection/rotateControls.tsx +++ b/app/src/modules/scene/controls/selection/rotateControls.tsx @@ -1,242 +1,242 @@ -import * as THREE from "three"; -import { useEffect, useMemo, useRef, useState } from "react"; -import { useFrame, useThree } from "@react-three/fiber"; -import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; -// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; -import { toast } from "react-toastify"; -import * as Types from "../../../../types/world/worldTypes"; - -function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) { - const { camera, controls, gl, scene, pointer, raycaster } = useThree(); - const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); - - const { toggleView } = useToggleView(); - const { selectedAssets, setSelectedAssets } = useSelectedAssets(); - const { floorItems, setFloorItems } = useFloorItems(); - const { socket } = useSocketStore(); - const itemsData = useRef([]); - - const prevPointerPosition = useRef(null); - - useEffect(() => { - if (!camera || !scene || toggleView || !itemsGroupRef.current) return; - - const canvasElement = gl.domElement; - canvasElement.tabIndex = 0; - - let isMoving = false; - - const onPointerDown = () => { - isMoving = false; - }; - - const onPointerMove = () => { - isMoving = true; - }; - - const onPointerUp = (event: PointerEvent) => { - if (!isMoving && rotatedObjects.length > 0 && event.button === 0) { - event.preventDefault(); - placeRotatedAssets(); - } - if (!isMoving && rotatedObjects.length > 0 && event.button === 2) { - event.preventDefault(); - - clearSelection(); - rotatedObjects.forEach((asset: any) => { - if (itemsGroupRef.current) { - itemsGroupRef.current.attach(asset); - } - }); - - setFloorItems([...floorItems, ...itemsData.current]); - - setRotatedObjects([]); - itemsData.current = []; - } - }; - - const onKeyDown = (event: KeyboardEvent) => { - if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || movedObjects.length > 0) return; - if (event.key.toLowerCase() === "r") { - if (selectedAssets.length > 0) { - rotateAssets(); - itemsData.current = floorItems.filter((item: { modeluuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); - } - } - if (event.key.toLowerCase() === "escape") { - event.preventDefault(); - - clearSelection(); - rotatedObjects.forEach((asset: any) => { - if (itemsGroupRef.current) { - itemsGroupRef.current.attach(asset); - } - }); - - setFloorItems([...floorItems, ...itemsData.current]); - - setRotatedObjects([]); - itemsData.current = []; - } - }; - - if (!toggleView) { - canvasElement.addEventListener("pointerdown", onPointerDown); - canvasElement.addEventListener("pointermove", onPointerMove); - canvasElement.addEventListener("pointerup", onPointerUp); - canvasElement.addEventListener("keydown", onKeyDown); - } - - return () => { - canvasElement.removeEventListener("pointerdown", onPointerDown); - canvasElement.removeEventListener("pointermove", onPointerMove); - canvasElement.removeEventListener("pointerup", onPointerUp); - canvasElement.removeEventListener("keydown", onKeyDown); - }; - }, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, rotatedObjects, movedObjects]); - - useFrame(() => { - if (rotatedObjects.length > 0) { - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - - if (point && prevPointerPosition.current) { - const box = new THREE.Box3(); - rotatedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj)); - const center = new THREE.Vector3(); - box.getCenter(center); - - const delta = new THREE.Vector3().subVectors(point, center); - const prevPointerPosition3D = new THREE.Vector3(prevPointerPosition.current.x, 0, prevPointerPosition.current.y); - - const angle = Math.atan2(delta.z, delta.x) - Math.atan2(prevPointerPosition3D.z - center.z, prevPointerPosition3D.x - center.x); - - selectionGroup.current.rotation.y += -angle; - - selectionGroup.current.position.sub(center); - selectionGroup.current.position.applyAxisAngle(new THREE.Vector3(0, 1, 0), -angle); - selectionGroup.current.position.add(center); - - prevPointerPosition.current = new THREE.Vector2(point.x, point.z); - } - } - }); - - const rotateAssets = () => { - const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); - setFloorItems(updatedItems); - - const box = new THREE.Box3(); - selectedAssets.forEach((asset: any) => box.expandByObject(asset)); - const center = new THREE.Vector3(); - box.getCenter(center); - - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - - if (point) { - prevPointerPosition.current = new THREE.Vector2(point.x, point.z); - } - - selectedAssets.forEach((asset: any) => { - selectionGroup.current.attach(asset); - }); - - setRotatedObjects(selectedAssets); - }; - - const placeRotatedAssets = () => { - if (rotatedObjects.length === 0) return; - - rotatedObjects.forEach(async (obj: THREE.Object3D) => { - const worldPosition = new THREE.Vector3(); - const worldQuaternion = new THREE.Quaternion(); - - obj.getWorldPosition(worldPosition); - obj.getWorldQuaternion(worldQuaternion); - - selectionGroup.current.remove(obj); - - obj.position.copy(worldPosition); - obj.quaternion.copy(worldQuaternion); - - - if (itemsGroupRef.current) { - - const newFloorItem: Types.FloorItemType = { - modeluuid: obj.uuid, - modelname: obj.userData.name, - modelfileID: obj.userData.modelId, - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, - isLocked: false, - isVisible: true - }; - - setFloorItems((prevItems: Types.FloorItems) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); - - const email = localStorage.getItem("email"); - const organization = email ? email.split("@")[1].split(".")[0] : "default"; - - //REST - - // await setFloorItemApi( - // organization, - // obj.uuid, - // obj.userData.name, - // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, - // obj.userData.modelId, - // false, - // true, - // ); - - //SOCKET - - const data = { - organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, - modelfileID: newFloorItem.modelfileID, - position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, - isLocked: false, - isVisible: true, - socketId: socket.id, - }; - - socket.emit("v1:FloorItems:set", data); - - itemsGroupRef.current.add(obj); - } - }); - toast.success("Object rotated!"); - - itemsData.current = []; - clearSelection(); - } - - const clearSelection = () => { - selectionGroup.current.children = []; - selectionGroup.current.position.set(0, 0, 0); - selectionGroup.current.rotation.set(0, 0, 0); - setpastedObjects([]); - setDuplicatedObjects([]); - setMovedObjects([]); - setRotatedObjects([]); - setSelectedAssets([]); - } - - return ( - <> - ) -} - +import * as THREE from "three"; +import { useEffect, useMemo, useRef, useState } from "react"; +import { useFrame, useThree } from "@react-three/fiber"; +import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; +// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; +import { toast } from "react-toastify"; +import * as Types from "../../../../types/world/worldTypes"; + +function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) { + const { camera, controls, gl, scene, pointer, raycaster } = useThree(); + const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); + + const { toggleView } = useToggleView(); + const { selectedAssets, setSelectedAssets } = useSelectedAssets(); + const { floorItems, setFloorItems } = useFloorItems(); + const { socket } = useSocketStore(); + const itemsData = useRef([]); + + const prevPointerPosition = useRef(null); + + useEffect(() => { + if (!camera || !scene || toggleView || !itemsGroupRef.current) return; + + const canvasElement = gl.domElement; + canvasElement.tabIndex = 0; + + let isMoving = false; + + const onPointerDown = () => { + isMoving = false; + }; + + const onPointerMove = () => { + isMoving = true; + }; + + const onPointerUp = (event: PointerEvent) => { + if (!isMoving && rotatedObjects.length > 0 && event.button === 0) { + event.preventDefault(); + placeRotatedAssets(); + } + if (!isMoving && rotatedObjects.length > 0 && event.button === 2) { + event.preventDefault(); + + clearSelection(); + rotatedObjects.forEach((asset: any) => { + if (itemsGroupRef.current) { + itemsGroupRef.current.attach(asset); + } + }); + + setFloorItems([...floorItems, ...itemsData.current]); + + setRotatedObjects([]); + itemsData.current = []; + } + }; + + const onKeyDown = (event: KeyboardEvent) => { + if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || movedObjects.length > 0) return; + if (event.key.toLowerCase() === "r") { + if (selectedAssets.length > 0) { + rotateAssets(); + itemsData.current = floorItems.filter((item: { modeluuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); + } + } + if (event.key.toLowerCase() === "escape") { + event.preventDefault(); + + clearSelection(); + rotatedObjects.forEach((asset: any) => { + if (itemsGroupRef.current) { + itemsGroupRef.current.attach(asset); + } + }); + + setFloorItems([...floorItems, ...itemsData.current]); + + setRotatedObjects([]); + itemsData.current = []; + } + }; + + if (!toggleView) { + canvasElement.addEventListener("pointerdown", onPointerDown); + canvasElement.addEventListener("pointermove", onPointerMove); + canvasElement.addEventListener("pointerup", onPointerUp); + canvasElement.addEventListener("keydown", onKeyDown); + } + + return () => { + canvasElement.removeEventListener("pointerdown", onPointerDown); + canvasElement.removeEventListener("pointermove", onPointerMove); + canvasElement.removeEventListener("pointerup", onPointerUp); + canvasElement.removeEventListener("keydown", onKeyDown); + }; + }, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, rotatedObjects, movedObjects]); + + useFrame(() => { + if (rotatedObjects.length > 0) { + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + + if (point && prevPointerPosition.current) { + const box = new THREE.Box3(); + rotatedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj)); + const center = new THREE.Vector3(); + box.getCenter(center); + + const delta = new THREE.Vector3().subVectors(point, center); + const prevPointerPosition3D = new THREE.Vector3(prevPointerPosition.current.x, 0, prevPointerPosition.current.y); + + const angle = Math.atan2(delta.z, delta.x) - Math.atan2(prevPointerPosition3D.z - center.z, prevPointerPosition3D.x - center.x); + + selectionGroup.current.rotation.y += -angle; + + selectionGroup.current.position.sub(center); + selectionGroup.current.position.applyAxisAngle(new THREE.Vector3(0, 1, 0), -angle); + selectionGroup.current.position.add(center); + + prevPointerPosition.current = new THREE.Vector2(point.x, point.z); + } + } + }); + + const rotateAssets = () => { + const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); + setFloorItems(updatedItems); + + const box = new THREE.Box3(); + selectedAssets.forEach((asset: any) => box.expandByObject(asset)); + const center = new THREE.Vector3(); + box.getCenter(center); + + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + + if (point) { + prevPointerPosition.current = new THREE.Vector2(point.x, point.z); + } + + selectedAssets.forEach((asset: any) => { + selectionGroup.current.attach(asset); + }); + + setRotatedObjects(selectedAssets); + }; + + const placeRotatedAssets = () => { + if (rotatedObjects.length === 0) return; + + rotatedObjects.forEach(async (obj: THREE.Object3D) => { + const worldPosition = new THREE.Vector3(); + const worldQuaternion = new THREE.Quaternion(); + + obj.getWorldPosition(worldPosition); + obj.getWorldQuaternion(worldQuaternion); + + selectionGroup.current.remove(obj); + + obj.position.copy(worldPosition); + obj.quaternion.copy(worldQuaternion); + + + if (itemsGroupRef.current) { + + const newFloorItem: Types.FloorItemType = { + modeluuid: obj.uuid, + modelname: obj.userData.name, + modelfileID: obj.userData.modelId, + position: [worldPosition.x, worldPosition.y, worldPosition.z], + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, + isLocked: false, + isVisible: true + }; + + setFloorItems((prevItems: Types.FloorItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + const email = localStorage.getItem("email"); + const organization = email ? email.split("@")[1].split(".")[0] : "default"; + + //REST + + // await setFloorItemApi( + // organization, + // obj.uuid, + // obj.userData.name, + // [worldPosition.x, worldPosition.y, worldPosition.z], + // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, + // obj.userData.modelId, + // false, + // true, + // ); + + //SOCKET + + const data = { + organization, + modeluuid: newFloorItem.modeluuid, + modelname: newFloorItem.modelname, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id, + }; + + socket.emit("v1:FloorItems:set", data); + + itemsGroupRef.current.add(obj); + } + }); + toast.success("Object rotated!"); + + itemsData.current = []; + clearSelection(); + } + + const clearSelection = () => { + selectionGroup.current.children = []; + selectionGroup.current.position.set(0, 0, 0); + selectionGroup.current.rotation.set(0, 0, 0); + setpastedObjects([]); + setDuplicatedObjects([]); + setMovedObjects([]); + setRotatedObjects([]); + setSelectedAssets([]); + } + + return ( + <> + ) +} + export default RotateControls \ No newline at end of file diff --git a/app/src/modules/scene/controls/selection/selectionControls.tsx b/app/src/modules/scene/controls/selection/selectionControls.tsx index 4f62c50..086842e 100644 --- a/app/src/modules/scene/controls/selection/selectionControls.tsx +++ b/app/src/modules/scene/controls/selection/selectionControls.tsx @@ -1,237 +1,237 @@ -import * as THREE from "three"; -import { useEffect, useMemo, useRef, useState } from "react"; -import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox"; -import { SelectionHelper } from "./selectionHelper"; -import { useFrame, useThree } from "@react-three/fiber"; -import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; -import BoundingBox from "./boundingBoxHelper"; -import { toast } from "react-toastify"; -// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi'; -import * as Types from "../../../../types/world/worldTypes"; - -import DuplicationControls from "./duplicationControls"; -import CopyPasteControls from "./copyPasteControls"; -import MoveControls from "./moveControls"; -import RotateControls from "./rotateControls"; - -const SelectionControls: React.FC = () => { - const { camera, controls, gl, scene, pointer } = useThree(); - const itemsGroupRef = useRef(undefined); - const selectionGroup = useRef() as Types.RefGroup; - const { toggleView } = useToggleView(); - const { selectedAssets, setSelectedAssets } = useSelectedAssets(); - const [movedObjects, setMovedObjects] = useState([]); - const [rotatedObjects, setRotatedObjects] = useState([]); - const [copiedObjects, setCopiedObjects] = useState([]); - const [pastedObjects, setpastedObjects] = useState([]); - const [duplicatedObjects, setDuplicatedObjects] = useState([]); - const boundingBoxRef = useRef(); - const { floorItems, setFloorItems } = useFloorItems(); - const { socket } = useSocketStore(); - const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]); - - useEffect(() => { - if (!camera || !scene || toggleView) return; - - const canvasElement = gl.domElement; - canvasElement.tabIndex = 0; - - const itemsGroup: any = scene.getObjectByName("itemsGroup"); - itemsGroupRef.current = itemsGroup; - - let isSelecting = false; - let isCtrlSelecting = false; - - const helper = new SelectionHelper(gl); - - if (!itemsGroup) { - toast.warn("itemsGroup not found in the scene."); - return; - } - - const onPointerDown = (event: PointerEvent) => { - if (event.button !== 0) return - isSelecting = false; - isCtrlSelecting = event.ctrlKey; - if (event.ctrlKey && duplicatedObjects.length === 0) { - if (controls) (controls as any).enabled = false; - selectionBox.startPoint.set(pointer.x, pointer.y, 0); - } - }; - - const onPointerMove = (event: PointerEvent) => { - isSelecting = true; - if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) { - selectionBox.endPoint.set(pointer.x, pointer.y, 0); - } - }; - - const onPointerUp = (event: PointerEvent) => { - if (isSelecting && isCtrlSelecting) { - isCtrlSelecting = false; - isSelecting = false; - if (event.ctrlKey && duplicatedObjects.length === 0) { - selectAssets(); - } - } else if (!isSelecting && selectedAssets.length > 0 && ((pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) || event.button !== 0)) { - clearSelection(); - helper.enabled = true; - isCtrlSelecting = false; - } - }; - - const onKeyDown = (event: KeyboardEvent) => { - if (movedObjects.length > 0 || rotatedObjects.length > 0) return; - if (event.key.toLowerCase() === "escape") { - event.preventDefault(); - clearSelection(); - } - if (event.key.toLowerCase() === "delete") { - event.preventDefault(); - deleteSelection(); - } - }; - - const onContextMenu = (event: MouseEvent) => { - event.preventDefault(); - clearSelection(); - } - - if (!toggleView) { - helper.enabled = true; - canvasElement.addEventListener("pointerdown", onPointerDown); - canvasElement.addEventListener("pointermove", onPointerMove); - canvasElement.addEventListener("contextmenu", onContextMenu); - canvasElement.addEventListener("pointerup", onPointerUp); - canvasElement.addEventListener("keydown", onKeyDown); - } - - return () => { - canvasElement.removeEventListener("pointerdown", onPointerDown); - canvasElement.removeEventListener("pointermove", onPointerMove); - canvasElement.removeEventListener("contextmenu", onContextMenu); - canvasElement.removeEventListener("pointerup", onPointerUp); - canvasElement.removeEventListener("keydown", onKeyDown); - helper.enabled = false; - helper.dispose(); - }; - }, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, floorItems, rotatedObjects]); - - useFrame(() => { - if (pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { - selectionGroup.current.position.set(0, 0, 0); - } - }); - - const selectAssets = () => { - selectionBox.endPoint.set(pointer.x, pointer.y, 0); - if (controls) (controls as any).enabled = true; - - let selectedObjects = selectionBox.select(); - let Objects = new Set(); - - selectedObjects.map((object) => { - let currentObject: THREE.Object3D | null = object; - while (currentObject) { - if (currentObject.userData.modelId) { - Objects.add(currentObject); - break; - } - currentObject = currentObject.parent || null; - } - }) - - if (Objects.size === 0) { - clearSelection(); - return; - } - - const updatedSelections = new Set(selectedAssets); - Objects.forEach((obj) => { - updatedSelections.has(obj) ? updatedSelections.delete(obj) : updatedSelections.add(obj); - }); - - const selected = Array.from(updatedSelections); - - setSelectedAssets(selected); - }; - - const clearSelection = () => { - selectionGroup.current.children = []; - selectionGroup.current.position.set(0, 0, 0); - selectionGroup.current.rotation.set(0, 0, 0); - setpastedObjects([]); - setDuplicatedObjects([]); - setSelectedAssets([]); - } - - const deleteSelection = () => { - if (selectedAssets.length > 0 && duplicatedObjects.length === 0) { - const email = localStorage.getItem('email'); - const organization = (email!.split("@")[1]).split(".")[0]; - - const storedItems = JSON.parse(localStorage.getItem("FloorItems") || '[]'); - const selectedUUIDs = selectedAssets.map((mesh: THREE.Object3D) => mesh.uuid); - - const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid)); - localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); - - selectedAssets.forEach((selectedMesh: THREE.Object3D) => { - - //REST - - // const response = await deleteFloorItem(organization, selectedMesh.uuid, selectedMesh.userData.name); - - //SOCKET - - const data = { - organization: organization, - modeluuid: selectedMesh.uuid, - modelname: selectedMesh.userData.name, - socketId: socket.id - }; - - socket.emit('v1:FloorItems:delete', data); - - selectedMesh.traverse((child: THREE.Object3D) => { - if (child instanceof THREE.Mesh) { - if (child.geometry) child.geometry.dispose(); - if (Array.isArray(child.material)) { - child.material.forEach((material) => { - if (material.map) material.map.dispose(); - material.dispose(); - }); - } else if (child.material) { - if (child.material.map) child.material.map.dispose(); - child.material.dispose(); - } - } - }); - - itemsGroupRef.current?.remove(selectedMesh); - }); - - const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid)); - setFloorItems(updatedItems); - - } - toast.success("Selected models removed!"); - clearSelection(); - }; - - return ( - <> - - - - - - - - - - - ); -}; - +import * as THREE from "three"; +import { useEffect, useMemo, useRef, useState } from "react"; +import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox"; +import { SelectionHelper } from "./selectionHelper"; +import { useFrame, useThree } from "@react-three/fiber"; +import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; +import BoundingBox from "./boundingBoxHelper"; +import { toast } from "react-toastify"; +// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi'; +import * as Types from "../../../../types/world/worldTypes"; + +import DuplicationControls from "./duplicationControls"; +import CopyPasteControls from "./copyPasteControls"; +import MoveControls from "./moveControls"; +import RotateControls from "./rotateControls"; + +const SelectionControls: React.FC = () => { + const { camera, controls, gl, scene, pointer } = useThree(); + const itemsGroupRef = useRef(undefined); + const selectionGroup = useRef() as Types.RefGroup; + const { toggleView } = useToggleView(); + const { selectedAssets, setSelectedAssets } = useSelectedAssets(); + const [movedObjects, setMovedObjects] = useState([]); + const [rotatedObjects, setRotatedObjects] = useState([]); + const [copiedObjects, setCopiedObjects] = useState([]); + const [pastedObjects, setpastedObjects] = useState([]); + const [duplicatedObjects, setDuplicatedObjects] = useState([]); + const boundingBoxRef = useRef(); + const { floorItems, setFloorItems } = useFloorItems(); + const { socket } = useSocketStore(); + const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]); + + useEffect(() => { + if (!camera || !scene || toggleView) return; + + const canvasElement = gl.domElement; + canvasElement.tabIndex = 0; + + const itemsGroup: any = scene.getObjectByName("itemsGroup"); + itemsGroupRef.current = itemsGroup; + + let isSelecting = false; + let isCtrlSelecting = false; + + const helper = new SelectionHelper(gl); + + if (!itemsGroup) { + toast.warn("itemsGroup not found in the scene."); + return; + } + + const onPointerDown = (event: PointerEvent) => { + if (event.button !== 0) return + isSelecting = false; + isCtrlSelecting = event.ctrlKey; + if (event.ctrlKey && duplicatedObjects.length === 0) { + if (controls) (controls as any).enabled = false; + selectionBox.startPoint.set(pointer.x, pointer.y, 0); + } + }; + + const onPointerMove = (event: PointerEvent) => { + isSelecting = true; + if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) { + selectionBox.endPoint.set(pointer.x, pointer.y, 0); + } + }; + + const onPointerUp = (event: PointerEvent) => { + if (isSelecting && isCtrlSelecting) { + isCtrlSelecting = false; + isSelecting = false; + if (event.ctrlKey && duplicatedObjects.length === 0) { + selectAssets(); + } + } else if (!isSelecting && selectedAssets.length > 0 && ((pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) || event.button !== 0)) { + clearSelection(); + helper.enabled = true; + isCtrlSelecting = false; + } + }; + + const onKeyDown = (event: KeyboardEvent) => { + if (movedObjects.length > 0 || rotatedObjects.length > 0) return; + if (event.key.toLowerCase() === "escape") { + event.preventDefault(); + clearSelection(); + } + if (event.key.toLowerCase() === "delete") { + event.preventDefault(); + deleteSelection(); + } + }; + + const onContextMenu = (event: MouseEvent) => { + event.preventDefault(); + clearSelection(); + } + + if (!toggleView) { + helper.enabled = true; + canvasElement.addEventListener("pointerdown", onPointerDown); + canvasElement.addEventListener("pointermove", onPointerMove); + canvasElement.addEventListener("contextmenu", onContextMenu); + canvasElement.addEventListener("pointerup", onPointerUp); + canvasElement.addEventListener("keydown", onKeyDown); + } + + return () => { + canvasElement.removeEventListener("pointerdown", onPointerDown); + canvasElement.removeEventListener("pointermove", onPointerMove); + canvasElement.removeEventListener("contextmenu", onContextMenu); + canvasElement.removeEventListener("pointerup", onPointerUp); + canvasElement.removeEventListener("keydown", onKeyDown); + helper.enabled = false; + helper.dispose(); + }; + }, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, floorItems, rotatedObjects]); + + useFrame(() => { + if (pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { + selectionGroup.current.position.set(0, 0, 0); + } + }); + + const selectAssets = () => { + selectionBox.endPoint.set(pointer.x, pointer.y, 0); + if (controls) (controls as any).enabled = true; + + let selectedObjects = selectionBox.select(); + let Objects = new Set(); + + selectedObjects.map((object) => { + let currentObject: THREE.Object3D | null = object; + while (currentObject) { + if (currentObject.userData.modelId) { + Objects.add(currentObject); + break; + } + currentObject = currentObject.parent || null; + } + }) + + if (Objects.size === 0) { + clearSelection(); + return; + } + + const updatedSelections = new Set(selectedAssets); + Objects.forEach((obj) => { + updatedSelections.has(obj) ? updatedSelections.delete(obj) : updatedSelections.add(obj); + }); + + const selected = Array.from(updatedSelections); + + setSelectedAssets(selected); + }; + + const clearSelection = () => { + selectionGroup.current.children = []; + selectionGroup.current.position.set(0, 0, 0); + selectionGroup.current.rotation.set(0, 0, 0); + setpastedObjects([]); + setDuplicatedObjects([]); + setSelectedAssets([]); + } + + const deleteSelection = () => { + if (selectedAssets.length > 0 && duplicatedObjects.length === 0) { + const email = localStorage.getItem('email'); + const organization = (email!.split("@")[1]).split(".")[0]; + + const storedItems = JSON.parse(localStorage.getItem("FloorItems") || '[]'); + const selectedUUIDs = selectedAssets.map((mesh: THREE.Object3D) => mesh.uuid); + + const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid)); + localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); + + selectedAssets.forEach((selectedMesh: THREE.Object3D) => { + + //REST + + // const response = await deleteFloorItem(organization, selectedMesh.uuid, selectedMesh.userData.name); + + //SOCKET + + const data = { + organization: organization, + modeluuid: selectedMesh.uuid, + modelname: selectedMesh.userData.name, + socketId: socket.id + }; + + socket.emit('v1:FloorItems:delete', data); + + selectedMesh.traverse((child: THREE.Object3D) => { + if (child instanceof THREE.Mesh) { + if (child.geometry) child.geometry.dispose(); + if (Array.isArray(child.material)) { + child.material.forEach((material) => { + if (material.map) material.map.dispose(); + material.dispose(); + }); + } else if (child.material) { + if (child.material.map) child.material.map.dispose(); + child.material.dispose(); + } + } + }); + + itemsGroupRef.current?.remove(selectedMesh); + }); + + const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid)); + setFloorItems(updatedItems); + + } + toast.success("Selected models removed!"); + clearSelection(); + }; + + return ( + <> + + + + + + + + + + + ); +}; + export default SelectionControls; \ No newline at end of file diff --git a/app/src/modules/scene/controls/selection/selectionHelper.ts b/app/src/modules/scene/controls/selection/selectionHelper.ts index c1acaf6..ae37e67 100644 --- a/app/src/modules/scene/controls/selection/selectionHelper.ts +++ b/app/src/modules/scene/controls/selection/selectionHelper.ts @@ -1,115 +1,115 @@ -import { Vector2, WebGLRenderer } from 'three'; - -class SelectionHelper { - element: HTMLDivElement; - renderer: WebGLRenderer; - startPoint: Vector2; - pointTopLeft: Vector2; - pointBottomRight: Vector2; - isDown: boolean; - enabled: boolean; - - constructor(renderer: WebGLRenderer) { - this.element = document.createElement('div'); - this.element.style.position = 'fixed'; - this.element.style.border = '1px solid #55aaff'; - this.element.style.backgroundColor = 'rgba(75, 160, 255, 0.3)'; - this.element.style.pointerEvents = 'none'; - this.element.style.display = 'none'; - - this.renderer = renderer; - - this.startPoint = new Vector2(); - this.pointTopLeft = new Vector2(); - this.pointBottomRight = new Vector2(); - - this.isDown = false; - this.enabled = true; - - this.onPointerDown = this.onPointerDown.bind(this); - this.onPointerMove = this.onPointerMove.bind(this); - this.onPointerUp = this.onPointerUp.bind(this); - - this.renderer.domElement.addEventListener('pointerdown', this.onPointerDown); - this.renderer.domElement.addEventListener('pointermove', this.onPointerMove); - this.renderer.domElement.addEventListener('pointerup', this.onPointerUp); - window.addEventListener("blur", this.cleanup.bind(this)); - } - - dispose() { - this.enabled = false; - this.isDown = false; - this.cleanup(); - - this.renderer.domElement.removeEventListener("pointerdown", this.onPointerDown); - this.renderer.domElement.removeEventListener("pointermove", this.onPointerMove); - this.renderer.domElement.removeEventListener("pointerup", this.onPointerUp); - window.removeEventListener("blur", this.cleanup); - } - - private cleanup() { - this.isDown = false; - this.element.style.display = 'none'; - if (this.element.parentElement) { - this.element.parentElement.removeChild(this.element); - } - } - - onPointerDown(event: PointerEvent) { - if (!this.enabled || !event.ctrlKey || event.button !== 0) return; - - this.isDown = true; - this.onSelectStart(event); - } - - onPointerMove(event: PointerEvent) { - if (!this.enabled || !this.isDown || !event.ctrlKey) return; - - this.onSelectMove(event); - } - - onPointerUp() { - if (!this.enabled) return; - - this.isDown = false; - this.onSelectOver(); - } - - onSelectStart(event: PointerEvent) { - this.element.style.display = 'none'; - this.renderer.domElement.parentElement?.appendChild(this.element); - - this.element.style.left = `${event.clientX}px`; - this.element.style.top = `${event.clientY}px`; - this.element.style.width = '0px'; - this.element.style.height = '0px'; - - this.startPoint.x = event.clientX; - this.startPoint.y = event.clientY; - } - - onSelectMove(event: PointerEvent) { - if (!this.isDown) return; - - this.element.style.display = 'block'; - - this.pointBottomRight.x = Math.max(this.startPoint.x, event.clientX); - this.pointBottomRight.y = Math.max(this.startPoint.y, event.clientY); - this.pointTopLeft.x = Math.min(this.startPoint.x, event.clientX); - this.pointTopLeft.y = Math.min(this.startPoint.y, event.clientY); - - this.element.style.left = `${this.pointTopLeft.x}px`; - this.element.style.top = `${this.pointTopLeft.y}px`; - this.element.style.width = `${this.pointBottomRight.x - this.pointTopLeft.x}px`; - this.element.style.height = `${this.pointBottomRight.y - this.pointTopLeft.y}px`; - } - - onSelectOver() { - this.element.style.display = 'none'; - if (this.element.parentElement) { - this.element.parentElement.removeChild(this.element); - } - } -} - +import { Vector2, WebGLRenderer } from 'three'; + +class SelectionHelper { + element: HTMLDivElement; + renderer: WebGLRenderer; + startPoint: Vector2; + pointTopLeft: Vector2; + pointBottomRight: Vector2; + isDown: boolean; + enabled: boolean; + + constructor(renderer: WebGLRenderer) { + this.element = document.createElement('div'); + this.element.style.position = 'fixed'; + this.element.style.border = '1px solid #55aaff'; + this.element.style.backgroundColor = 'rgba(75, 160, 255, 0.3)'; + this.element.style.pointerEvents = 'none'; + this.element.style.display = 'none'; + + this.renderer = renderer; + + this.startPoint = new Vector2(); + this.pointTopLeft = new Vector2(); + this.pointBottomRight = new Vector2(); + + this.isDown = false; + this.enabled = true; + + this.onPointerDown = this.onPointerDown.bind(this); + this.onPointerMove = this.onPointerMove.bind(this); + this.onPointerUp = this.onPointerUp.bind(this); + + this.renderer.domElement.addEventListener('pointerdown', this.onPointerDown); + this.renderer.domElement.addEventListener('pointermove', this.onPointerMove); + this.renderer.domElement.addEventListener('pointerup', this.onPointerUp); + window.addEventListener("blur", this.cleanup.bind(this)); + } + + dispose() { + this.enabled = false; + this.isDown = false; + this.cleanup(); + + this.renderer.domElement.removeEventListener("pointerdown", this.onPointerDown); + this.renderer.domElement.removeEventListener("pointermove", this.onPointerMove); + this.renderer.domElement.removeEventListener("pointerup", this.onPointerUp); + window.removeEventListener("blur", this.cleanup); + } + + private cleanup() { + this.isDown = false; + this.element.style.display = 'none'; + if (this.element.parentElement) { + this.element.parentElement.removeChild(this.element); + } + } + + onPointerDown(event: PointerEvent) { + if (!this.enabled || !event.ctrlKey || event.button !== 0) return; + + this.isDown = true; + this.onSelectStart(event); + } + + onPointerMove(event: PointerEvent) { + if (!this.enabled || !this.isDown || !event.ctrlKey) return; + + this.onSelectMove(event); + } + + onPointerUp() { + if (!this.enabled) return; + + this.isDown = false; + this.onSelectOver(); + } + + onSelectStart(event: PointerEvent) { + this.element.style.display = 'none'; + this.renderer.domElement.parentElement?.appendChild(this.element); + + this.element.style.left = `${event.clientX}px`; + this.element.style.top = `${event.clientY}px`; + this.element.style.width = '0px'; + this.element.style.height = '0px'; + + this.startPoint.x = event.clientX; + this.startPoint.y = event.clientY; + } + + onSelectMove(event: PointerEvent) { + if (!this.isDown) return; + + this.element.style.display = 'block'; + + this.pointBottomRight.x = Math.max(this.startPoint.x, event.clientX); + this.pointBottomRight.y = Math.max(this.startPoint.y, event.clientY); + this.pointTopLeft.x = Math.min(this.startPoint.x, event.clientX); + this.pointTopLeft.y = Math.min(this.startPoint.y, event.clientY); + + this.element.style.left = `${this.pointTopLeft.x}px`; + this.element.style.top = `${this.pointTopLeft.y}px`; + this.element.style.width = `${this.pointBottomRight.x - this.pointTopLeft.x}px`; + this.element.style.height = `${this.pointBottomRight.y - this.pointTopLeft.y}px`; + } + + onSelectOver() { + this.element.style.display = 'none'; + if (this.element.parentElement) { + this.element.parentElement.removeChild(this.element); + } + } +} + export { SelectionHelper }; \ No newline at end of file diff --git a/app/src/modules/scene/controls/transformControls.tsx b/app/src/modules/scene/controls/transformControls.tsx index 5e8c213..7047f35 100644 --- a/app/src/modules/scene/controls/transformControls.tsx +++ b/app/src/modules/scene/controls/transformControls.tsx @@ -1,120 +1,120 @@ -import { TransformControls } from "@react-three/drei"; -import * as THREE from "three"; -import { useselectedFloorItem, useObjectPosition, useObjectScale, useObjectRotation, useTransformMode, useFloorItems, useSocketStore, useActiveTool } from "../../../store/store"; -import { useThree } from "@react-three/fiber"; - -import * as Types from '../../../types/world/worldTypes'; -import { useEffect } from "react"; - -export default function TransformControl() { - const state = useThree(); - const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem(); - const { objectPosition, setObjectPosition } = useObjectPosition(); - const { objectScale, setObjectScale } = useObjectScale(); - const { objectRotation, setObjectRotation } = useObjectRotation(); - const { transformMode, setTransformMode } = useTransformMode(); - const { floorItems, setFloorItems } = useFloorItems(); - const { activeTool, setActiveTool } = useActiveTool(); - const { socket } = useSocketStore(); - - function handleObjectChange() { - if (selectedFloorItem && transformMode) { - setObjectPosition(selectedFloorItem.position); - setObjectScale(selectedFloorItem.scale); - setObjectRotation({ - x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x), - y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y), - z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z), - }); - } - } - function handleMouseUp() { - if (selectedFloorItem) { - setObjectPosition(selectedFloorItem.position); - setObjectScale(selectedFloorItem.scale); - setObjectRotation({ - x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x), - y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y), - z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z), - }); - } - setFloorItems((prevItems: Types.FloorItems) => { - if (!prevItems) { - return - } - let updatedItem: any = null; - const updatedItems = prevItems.map((item) => { - if (item.modeluuid === selectedFloorItem?.uuid) { - updatedItem = { - ...item, - position: [selectedFloorItem.position.x, selectedFloorItem.position.y, selectedFloorItem.position.z,] as [number, number, number], - rotation: { x: selectedFloorItem.rotation.x, y: selectedFloorItem.rotation.y, z: selectedFloorItem.rotation.z, }, - }; - return updatedItem; - } - return item; - }); - if (updatedItem && selectedFloorItem) { - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - //REST - - // setFloorItemApi( - // organization, - // updatedItem.modeluuid, - // updatedItem.modelname, - // [selectedFloorItem.position.x, selectedFloorItem.position.y, selectedFloorItem.position.z,], - // { "x": selectedFloorItem.rotation.x, "y": selectedFloorItem.rotation.y, "z": selectedFloorItem.rotation.z }, - // false, - // true, - // ); - - //SOCKET - - const data = { - organization: organization, - modeluuid: updatedItem.modeluuid, - modelname: updatedItem.modelname, - position: [selectedFloorItem.position.x, selectedFloorItem.position.y, selectedFloorItem.position.z], - rotation: { "x": selectedFloorItem.rotation.x, "y": selectedFloorItem.rotation.y, "z": selectedFloorItem.rotation.z }, - isLocked: false, - isVisible: true, - socketId: socket.id - } - - socket.emit('v1:FloorItems:set', data); - } - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); - } - - useEffect(() => { - if (activeTool === "Add pillar" || activeTool === "Delete") { - if (state.controls) { - const target = (state.controls as any).getTarget(new THREE.Vector3()); - (state.controls as any).setTarget(target.x, 0, target.z, true); - } - setselectedFloorItem(null); - { - setObjectPosition({ x: undefined, y: undefined, z: undefined }); - setObjectScale({ x: undefined, y: undefined, z: undefined }); - setObjectRotation({ x: undefined, y: undefined, z: undefined }); - } - } - }, [activeTool]); - - return ( - <> - {(selectedFloorItem && transformMode) && - - } - - ); -} +import { TransformControls } from "@react-three/drei"; +import * as THREE from "three"; +import { useselectedFloorItem, useObjectPosition, useObjectScale, useObjectRotation, useTransformMode, useFloorItems, useSocketStore, useActiveTool } from "../../../store/store"; +import { useThree } from "@react-three/fiber"; + +import * as Types from '../../../types/world/worldTypes'; +import { useEffect } from "react"; + +export default function TransformControl() { + const state = useThree(); + const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem(); + const { objectPosition, setObjectPosition } = useObjectPosition(); + const { objectScale, setObjectScale } = useObjectScale(); + const { objectRotation, setObjectRotation } = useObjectRotation(); + const { transformMode, setTransformMode } = useTransformMode(); + const { floorItems, setFloorItems } = useFloorItems(); + const { activeTool, setActiveTool } = useActiveTool(); + const { socket } = useSocketStore(); + + function handleObjectChange() { + if (selectedFloorItem && transformMode) { + setObjectPosition(selectedFloorItem.position); + setObjectScale(selectedFloorItem.scale); + setObjectRotation({ + x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x), + y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y), + z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z), + }); + } + } + function handleMouseUp() { + if (selectedFloorItem) { + setObjectPosition(selectedFloorItem.position); + setObjectScale(selectedFloorItem.scale); + setObjectRotation({ + x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x), + y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y), + z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z), + }); + } + setFloorItems((prevItems: Types.FloorItems) => { + if (!prevItems) { + return + } + let updatedItem: any = null; + const updatedItems = prevItems.map((item) => { + if (item.modeluuid === selectedFloorItem?.uuid) { + updatedItem = { + ...item, + position: [selectedFloorItem.position.x, selectedFloorItem.position.y, selectedFloorItem.position.z,] as [number, number, number], + rotation: { x: selectedFloorItem.rotation.x, y: selectedFloorItem.rotation.y, z: selectedFloorItem.rotation.z, }, + }; + return updatedItem; + } + return item; + }); + if (updatedItem && selectedFloorItem) { + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + //REST + + // setFloorItemApi( + // organization, + // updatedItem.modeluuid, + // updatedItem.modelname, + // [selectedFloorItem.position.x, selectedFloorItem.position.y, selectedFloorItem.position.z,], + // { "x": selectedFloorItem.rotation.x, "y": selectedFloorItem.rotation.y, "z": selectedFloorItem.rotation.z }, + // false, + // true, + // ); + + //SOCKET + + const data = { + organization: organization, + modeluuid: updatedItem.modeluuid, + modelname: updatedItem.modelname, + position: [selectedFloorItem.position.x, selectedFloorItem.position.y, selectedFloorItem.position.z], + rotation: { "x": selectedFloorItem.rotation.x, "y": selectedFloorItem.rotation.y, "z": selectedFloorItem.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id + } + + socket.emit('v1:FloorItems:set', data); + } + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + } + + useEffect(() => { + if (activeTool === "Add pillar" || activeTool === "Delete") { + if (state.controls) { + const target = (state.controls as any).getTarget(new THREE.Vector3()); + (state.controls as any).setTarget(target.x, 0, target.z, true); + } + setselectedFloorItem(null); + { + setObjectPosition({ x: undefined, y: undefined, z: undefined }); + setObjectScale({ x: undefined, y: undefined, z: undefined }); + setObjectRotation({ x: undefined, y: undefined, z: undefined }); + } + } + }, [activeTool]); + + return ( + <> + {(selectedFloorItem && transformMode) && + + } + + ); +} diff --git a/app/src/modules/scene/environment/ground.tsx b/app/src/modules/scene/environment/ground.tsx index 0251ba6..6a54577 100644 --- a/app/src/modules/scene/environment/ground.tsx +++ b/app/src/modules/scene/environment/ground.tsx @@ -1,22 +1,22 @@ -import * as THREE from 'three'; -import { useToggleView } from '../../../store/store'; -import * as CONSTANTS from '../../../types/world/worldConstants'; - -const Ground = ({ grid, plane }: any) => { - const { toggleView, setToggleView } = useToggleView(); - - return ( - - - - - - - - - - - ) -} - +import * as THREE from 'three'; +import { useToggleView } from '../../../store/store'; +import * as CONSTANTS from '../../../types/world/worldConstants'; + +const Ground = ({ grid, plane }: any) => { + const { toggleView, setToggleView } = useToggleView(); + + return ( + + + + + + + + + + + ) +} + export default Ground; \ No newline at end of file diff --git a/app/src/modules/scene/environment/shadow.tsx b/app/src/modules/scene/environment/shadow.tsx index 7db2104..62202b3 100644 --- a/app/src/modules/scene/environment/shadow.tsx +++ b/app/src/modules/scene/environment/shadow.tsx @@ -1,84 +1,84 @@ -import { useRef, useEffect} from 'react'; -import { useThree } from '@react-three/fiber'; -import * as THREE from 'three'; -import { useAzimuth, useElevation, useShadows, useSunPosition, useFloorItems, useWallItems } from '../../../store/store'; -import * as CONSTANTS from '../../../types/world/worldConstants'; -const shadowWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/shadowWorker', import.meta.url)); - -export default function Shadows() { - const { shadows, setShadows } = useShadows(); - const { sunPosition, setSunPosition } = useSunPosition(); - const lightRef = useRef(null); - const targetRef = useRef(null); - const { controls, gl } = useThree(); - const { elevation, setElevation } = useElevation(); - const { azimuth, setAzimuth } = useAzimuth(); - const { floorItems } = useFloorItems(); - const { wallItems } = useWallItems(); - - useEffect(() => { - gl.shadowMap.enabled = true; - gl.shadowMap.type = THREE.PCFShadowMap; - }, [gl, floorItems, wallItems]); - - useEffect(() => { - if (lightRef.current && targetRef.current) { - lightRef.current.target = targetRef.current; - } - }, []); - - useEffect(() => { - shadowWorker.onmessage = (event) => { - const { lightPosition, controlsTarget } = event.data; - if (lightRef.current && targetRef.current && controls) { - lightRef.current.position.copy(lightPosition); - targetRef.current.position.copy(controlsTarget); - } - }; - }, [shadowWorker, controls]); - - const updateShadows = () => { - if (controls && shadowWorker) { - const offsetDistance = CONSTANTS.shadowConfig.shadowOffset; - const controlsTarget = (controls as any).getTarget(); - shadowWorker.postMessage({ controlsTarget, sunPosition, offsetDistance }); - } - }; - - useEffect(() => { - if (controls && shadows) { - updateShadows(); - (controls as any).addEventListener('update', updateShadows); - return () => { - (controls as any).removeEventListener('update', updateShadows); - }; - } - }, [controls, elevation, azimuth, shadows]); - - return ( - <> - {/* {(lightRef.current?.shadow) && - - } */} - - - - - - - - ); +import { useRef, useEffect} from 'react'; +import { useThree } from '@react-three/fiber'; +import * as THREE from 'three'; +import { useAzimuth, useElevation, useShadows, useSunPosition, useFloorItems, useWallItems } from '../../../store/store'; +import * as CONSTANTS from '../../../types/world/worldConstants'; +const shadowWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/shadowWorker', import.meta.url)); + +export default function Shadows() { + const { shadows, setShadows } = useShadows(); + const { sunPosition, setSunPosition } = useSunPosition(); + const lightRef = useRef(null); + const targetRef = useRef(null); + const { controls, gl } = useThree(); + const { elevation, setElevation } = useElevation(); + const { azimuth, setAzimuth } = useAzimuth(); + const { floorItems } = useFloorItems(); + const { wallItems } = useWallItems(); + + useEffect(() => { + gl.shadowMap.enabled = true; + gl.shadowMap.type = THREE.PCFShadowMap; + }, [gl, floorItems, wallItems]); + + useEffect(() => { + if (lightRef.current && targetRef.current) { + lightRef.current.target = targetRef.current; + } + }, []); + + useEffect(() => { + shadowWorker.onmessage = (event) => { + const { lightPosition, controlsTarget } = event.data; + if (lightRef.current && targetRef.current && controls) { + lightRef.current.position.copy(lightPosition); + targetRef.current.position.copy(controlsTarget); + } + }; + }, [shadowWorker, controls]); + + const updateShadows = () => { + if (controls && shadowWorker) { + const offsetDistance = CONSTANTS.shadowConfig.shadowOffset; + const controlsTarget = (controls as any).getTarget(); + shadowWorker.postMessage({ controlsTarget, sunPosition, offsetDistance }); + } + }; + + useEffect(() => { + if (controls && shadows) { + updateShadows(); + (controls as any).addEventListener('update', updateShadows); + return () => { + (controls as any).removeEventListener('update', updateShadows); + }; + } + }, [controls, elevation, azimuth, shadows]); + + return ( + <> + {/* {(lightRef.current?.shadow) && + + } */} + + + + + + + + ); } \ No newline at end of file diff --git a/app/src/modules/scene/environment/sky.tsx b/app/src/modules/scene/environment/sky.tsx index b2bb210..3be57ce 100644 --- a/app/src/modules/scene/environment/sky.tsx +++ b/app/src/modules/scene/environment/sky.tsx @@ -1,49 +1,49 @@ -import * as THREE from 'three'; -import { Sky } from "@react-three/drei"; -import { useAzimuth, useElevation, useSunPosition } from "../../../store/store"; -import { useEffect, useRef, useState } from "react"; -import * as CONSTANTS from '../../../types/world/worldConstants'; - -export default function Sun() { - const { elevation, setElevation } = useElevation(); - const { sunPosition, setSunPosition } = useSunPosition(); - const { azimuth, setAzimuth } = useAzimuth(); - const [turbidity, setTurbidity] = useState(CONSTANTS.skyConfig.defaultTurbidity); - const sunPositionRef = useRef(new THREE.Vector3(0, 0, 0)); - const [_, forceUpdate] = useState(0); - const maxTurbidity = CONSTANTS.skyConfig.maxTurbidity; - const minTurbidity = CONSTANTS.skyConfig.minTurbidity; - - useEffect(() => { - const phi = THREE.MathUtils.degToRad(90 - elevation); - const theta = THREE.MathUtils.degToRad(azimuth); - - const computedTurbidity = minTurbidity + ((elevation - 2) / (90 - 2)) * (maxTurbidity - minTurbidity); - setTurbidity(computedTurbidity); - - sunPositionRef.current.setFromSphericalCoords(1, phi, theta); - setSunPosition(sunPositionRef.current); - forceUpdate(prev => prev + 1); - }, [elevation, azimuth]); - - return ( - <> - {(azimuth !== undefined && elevation !== undefined) && ( - <> - - - )} - - ); -} +import * as THREE from 'three'; +import { Sky } from "@react-three/drei"; +import { useAzimuth, useElevation, useSunPosition } from "../../../store/store"; +import { useEffect, useRef, useState } from "react"; +import * as CONSTANTS from '../../../types/world/worldConstants'; + +export default function Sun() { + const { elevation, setElevation } = useElevation(); + const { sunPosition, setSunPosition } = useSunPosition(); + const { azimuth, setAzimuth } = useAzimuth(); + const [turbidity, setTurbidity] = useState(CONSTANTS.skyConfig.defaultTurbidity); + const sunPositionRef = useRef(new THREE.Vector3(0, 0, 0)); + const [_, forceUpdate] = useState(0); + const maxTurbidity = CONSTANTS.skyConfig.maxTurbidity; + const minTurbidity = CONSTANTS.skyConfig.minTurbidity; + + useEffect(() => { + const phi = THREE.MathUtils.degToRad(90 - elevation); + const theta = THREE.MathUtils.degToRad(azimuth); + + const computedTurbidity = minTurbidity + ((elevation - 2) / (90 - 2)) * (maxTurbidity - minTurbidity); + setTurbidity(computedTurbidity); + + sunPositionRef.current.setFromSphericalCoords(1, phi, theta); + setSunPosition(sunPositionRef.current); + forceUpdate(prev => prev + 1); + }, [elevation, azimuth]); + + return ( + <> + {(azimuth !== undefined && elevation !== undefined) && ( + <> + + + )} + + ); +} diff --git a/app/src/modules/scene/mqttTemp/drieHtmlTemp.tsx b/app/src/modules/scene/mqttTemp/drieHtmlTemp.tsx index 8604bcc..68c8c37 100644 --- a/app/src/modules/scene/mqttTemp/drieHtmlTemp.tsx +++ b/app/src/modules/scene/mqttTemp/drieHtmlTemp.tsx @@ -1,109 +1,109 @@ -import { Html } from "@react-three/drei"; -import * as THREE from "three"; -import * as Types from "../../../types/world/worldTypes"; -import { useDrieTemp, useDrieUIValue } from "../../../store/store" -import UI from "./ui"; -import { useEffect } from "react"; -import { useThree } from "@react-three/fiber"; - -export default function DrieHtmlTemp({ itemsGroup }: { itemsGroup: Types.RefGroup }) { - const { drieTemp, setDrieTemp } = useDrieTemp(); - const { drieUIValue, setDrieUIValue } = useDrieUIValue(); - const state = useThree(); - const { camera, raycaster } = state; - - useEffect(() => { - const canvasElement = state.gl.domElement; - let drag = false; - let isLeftMouseDown = false; - - const onMouseDown = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = true; - drag = false; - } - }; - - const onMouseMove = () => { - if (isLeftMouseDown) { - drag = true; - } - }; - - const onMouseUp = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = false; - if (drag) return; - if (!itemsGroup.current) return - let intersects = raycaster.intersectObjects(itemsGroup.current.children, true); - if (intersects.length > 0) { - let currentObject = intersects[0].object; - - while (currentObject) { - if (currentObject.name === "Scene") { - break; - } - currentObject = currentObject.parent as THREE.Object3D; - } - if (currentObject && (currentObject.userData.name === "SV2 Controll pannel" || currentObject.userData.name === "forklift")) { - const worldPos = new THREE.Vector3(); - currentObject.getWorldPosition(worldPos); - - const rightOffset = new THREE.Vector3(1, 0, 0); - const upOffset = new THREE.Vector3(0, 1, 0); - - currentObject.localToWorld(rightOffset); - currentObject.localToWorld(upOffset); - - const finalPosition = worldPos.clone().addScaledVector(rightOffset.sub(currentObject.position).normalize(), 2.5).addScaledVector(upOffset.sub(currentObject.position).normalize(), 2.3); - - setDrieTemp(finalPosition); - } else { - setDrieTemp(undefined); - } - } - else { - setDrieTemp(undefined); - } - } - }; - - - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - }; - }, []) - - return ( - <> - {drieTemp && - - - - - - } - - ) +import { Html } from "@react-three/drei"; +import * as THREE from "three"; +import * as Types from "../../../types/world/worldTypes"; +import { useDrieTemp, useDrieUIValue } from "../../../store/store" +import UI from "./ui"; +import { useEffect } from "react"; +import { useThree } from "@react-three/fiber"; + +export default function DrieHtmlTemp({ itemsGroup }: { itemsGroup: Types.RefGroup }) { + const { drieTemp, setDrieTemp } = useDrieTemp(); + const { drieUIValue, setDrieUIValue } = useDrieUIValue(); + const state = useThree(); + const { camera, raycaster } = state; + + useEffect(() => { + const canvasElement = state.gl.domElement; + let drag = false; + let isLeftMouseDown = false; + + const onMouseDown = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = true; + drag = false; + } + }; + + const onMouseMove = () => { + if (isLeftMouseDown) { + drag = true; + } + }; + + const onMouseUp = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = false; + if (drag) return; + if (!itemsGroup.current) return + let intersects = raycaster.intersectObjects(itemsGroup.current.children, true); + if (intersects.length > 0) { + let currentObject = intersects[0].object; + + while (currentObject) { + if (currentObject.name === "Scene") { + break; + } + currentObject = currentObject.parent as THREE.Object3D; + } + if (currentObject && (currentObject.userData.name === "SV2 Controll pannel" || currentObject.userData.name === "forklift")) { + const worldPos = new THREE.Vector3(); + currentObject.getWorldPosition(worldPos); + + const rightOffset = new THREE.Vector3(1, 0, 0); + const upOffset = new THREE.Vector3(0, 1, 0); + + currentObject.localToWorld(rightOffset); + currentObject.localToWorld(upOffset); + + const finalPosition = worldPos.clone().addScaledVector(rightOffset.sub(currentObject.position).normalize(), 2.5).addScaledVector(upOffset.sub(currentObject.position).normalize(), 2.3); + + setDrieTemp(finalPosition); + } else { + setDrieTemp(undefined); + } + } + else { + setDrieTemp(undefined); + } + } + }; + + + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + }; + }, []) + + return ( + <> + {drieTemp && + + + + + + } + + ) } \ No newline at end of file diff --git a/app/src/modules/scene/mqttTemp/ui.jsx b/app/src/modules/scene/mqttTemp/ui.jsx index cafff38..4d4c5fb 100644 --- a/app/src/modules/scene/mqttTemp/ui.jsx +++ b/app/src/modules/scene/mqttTemp/ui.jsx @@ -1,141 +1,141 @@ -export default function UI({ temperature, humidity, touch, header }) { - return ( -
-
- {header ? header : "Sensor Details"} -
-
-
-
- - - - - -
-
- Temperature -
-
- {temperature} -
-
-
-
- - - - - -
-
- Humidity -
-
- {humidity} -
-
-
-
-
-
- Touch Sensor -
-
- {touch === "True" ? "Active" : "In active"} -
-
-
-
- ); -} +export default function UI({ temperature, humidity, touch, header }) { + return ( +
+
+ {header ? header : "Sensor Details"} +
+
+
+
+ + + + + +
+
+ Temperature +
+
+ {temperature} +
+
+
+
+ + + + + +
+
+ Humidity +
+
+ {humidity} +
+
+
+
+
+
+ Touch Sensor +
+
+ {touch === "True" ? "Active" : "In active"} +
+
+
+
+ ); +} diff --git a/app/src/modules/scene/postProcessing/postProcessing.tsx b/app/src/modules/scene/postProcessing/postProcessing.tsx index 1c6c7ab..e1fc501 100644 --- a/app/src/modules/scene/postProcessing/postProcessing.tsx +++ b/app/src/modules/scene/postProcessing/postProcessing.tsx @@ -1,111 +1,111 @@ -import * as THREE from 'three' -import { EffectComposer, N8AO, Outline } from '@react-three/postprocessing' -import { BlendFunction } from 'postprocessing' -import { useDeletableFloorItem, useSelectedEventSphere, useSelectedPath, useSelectedWallItem, useselectedFloorItem } from '../../../store/store'; -import * as Types from '../../../types/world/worldTypes' -import * as CONSTANTS from '../../../types/world/worldConstants'; - -export default function PostProcessing() { - const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem(); - const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem(); - const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem(); - const { selectedEventSphere } = useSelectedEventSphere(); - const { selectedPath } = useSelectedPath(); - - function flattenChildren(children: any[]) { - const allChildren: any[] = []; - children.forEach(child => { - allChildren.push(child); - if (child.children && child.children.length > 0) { - allChildren.push(...flattenChildren(child.children)); - } - }); - return allChildren; - } - - return ( - <> - - - {deletableFloorItem && - - } - {selectedWallItem && - child.name !== "CSG_REF" - ) - } - selectionLayer={10} - width={3000} - blendFunction={BlendFunction.ALPHA} - edgeStrength={5} - resolutionScale={2} - pulseSpeed={0} - visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor} - hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor} - blur={true} - xRay={true} - />} - {selectedFloorItem && - - } - {selectedEventSphere && - - } - {selectedPath && - - } - - - ) +import * as THREE from 'three' +import { EffectComposer, N8AO, Outline } from '@react-three/postprocessing' +import { BlendFunction } from 'postprocessing' +import { useDeletableFloorItem, useSelectedActionSphere, useSelectedPath, useSelectedWallItem, useselectedFloorItem } from '../../../store/store'; +import * as Types from '../../../types/world/worldTypes' +import * as CONSTANTS from '../../../types/world/worldConstants'; + +export default function PostProcessing() { + const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem(); + const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem(); + const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem(); + const { selectedActionSphere } = useSelectedActionSphere(); + const { selectedPath } = useSelectedPath(); + + function flattenChildren(children: any[]) { + const allChildren: any[] = []; + children.forEach(child => { + allChildren.push(child); + if (child.children && child.children.length > 0) { + allChildren.push(...flattenChildren(child.children)); + } + }); + return allChildren; + } + + return ( + <> + + + {deletableFloorItem && + + } + {selectedWallItem && + child.name !== "CSG_REF" + ) + } + selectionLayer={10} + width={3000} + blendFunction={BlendFunction.ALPHA} + edgeStrength={5} + resolutionScale={2} + pulseSpeed={0} + visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor} + hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor} + blur={true} + xRay={true} + />} + {selectedFloorItem && + + } + {selectedActionSphere && + + } + {selectedPath && + + } + + + ) } \ No newline at end of file diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index d3e37fd..3aaff94 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -1,56 +1,56 @@ -import { useMemo } from "react"; -import { Canvas } from "@react-three/fiber"; -import { Environment, KeyboardControls } from "@react-three/drei"; - -import World from "./world/world"; -import Controls from "./controls/controls"; -import TransformControl from "./controls/transformControls"; -import PostProcessing from "./postProcessing/postProcessing" -import Sun from "./environment/sky"; -import CamModelsGroup from "../collaboration/collabCams"; -import Shadows from "./environment/shadow"; -import MqttEvents from "../../services/factoryBuilder/mqtt/mqttEvents"; - -import background from "../../assets/textures/hdr/mudroadpuresky2k.hdr"; -import SelectionControls from "./controls/selection/selectionControls"; -import MeasurementTool from "./tools/measurementTool"; -import Simulation from "../simulation/simulation"; -// import Simulation from "./simulationtemp/simulation"; - -export default function Scene() { - - const map = useMemo(() => [ - { name: "forward", keys: ["ArrowUp", "w", "W"] }, - { name: "backward", keys: ["ArrowDown", "s", "S"] }, - { name: "left", keys: ["ArrowLeft", "a", "A"] }, - { name: "right", keys: ["ArrowRight", "d", "D"] }, - // { name: "jump", keys: ["Space"] }, - ], []) - - return ( - - { - e.preventDefault(); - }} - > - - - - - - {/* */} - - - - - - - - - - ); -} +import { useMemo } from "react"; +import { Canvas } from "@react-three/fiber"; +import { Environment, KeyboardControls } from "@react-three/drei"; + +import World from "./world/world"; +import Controls from "./controls/controls"; +import TransformControl from "./controls/transformControls"; +import PostProcessing from "./postProcessing/postProcessing" +import Sun from "./environment/sky"; +import CamModelsGroup from "../collaboration/collabCams"; +import Shadows from "./environment/shadow"; +import MqttEvents from "../../services/factoryBuilder/mqtt/mqttEvents"; + +import background from "../../assets/textures/hdr/mudroadpuresky2k.hdr"; +import SelectionControls from "./controls/selection/selectionControls"; +import MeasurementTool from "./tools/measurementTool"; +import Simulation from "../simulation/simulation"; +// import Simulation from "./simulationtemp/simulation"; + +export default function Scene() { + + const map = useMemo(() => [ + { name: "forward", keys: ["ArrowUp", "w", "W"] }, + { name: "backward", keys: ["ArrowDown", "s", "S"] }, + { name: "left", keys: ["ArrowLeft", "a", "A"] }, + { name: "right", keys: ["ArrowRight", "d", "D"] }, + // { name: "jump", keys: ["Space"] }, + ], []) + + return ( + + { + e.preventDefault(); + }} + > + + + + + + {/* */} + + + + + + + + + + ); +} diff --git a/app/src/modules/scene/tools/measurementTool.tsx b/app/src/modules/scene/tools/measurementTool.tsx index 3e2a5a7..3c56a21 100644 --- a/app/src/modules/scene/tools/measurementTool.tsx +++ b/app/src/modules/scene/tools/measurementTool.tsx @@ -1,190 +1,190 @@ -import * as THREE from 'three'; -import { useEffect, useRef, useState } from 'react'; -import { useThree, useFrame } from '@react-three/fiber'; -import { useToolMode } from '../../../store/store'; -import { Html } from '@react-three/drei'; - -const MeasurementTool = () => { - const { gl, raycaster, pointer, camera, scene } = useThree(); - const { toolMode } = useToolMode(); - - const [points, setPoints] = useState([]); - const [tubeGeometry, setTubeGeometry] = useState(null); - const groupRef = useRef(null); - const [startConePosition, setStartConePosition] = useState(null); - const [endConePosition, setEndConePosition] = useState(null); - const [startConeQuaternion, setStartConeQuaternion] = useState(new THREE.Quaternion()); - const [endConeQuaternion, setEndConeQuaternion] = useState(new THREE.Quaternion()); - const [coneSize, setConeSize] = useState({ radius: 0.2, height: 0.5 }); - - - const MIN_RADIUS = 0.001, MAX_RADIUS = 0.1; - const MIN_CONE_RADIUS = 0.01, MAX_CONE_RADIUS = 0.4; - const MIN_CONE_HEIGHT = 0.035, MAX_CONE_HEIGHT = 2.0; - - useEffect(() => { - const canvasElement = gl.domElement; - let drag = false; - let isLeftMouseDown = false; - - const onMouseDown = () => { - isLeftMouseDown = true; - drag = false; - }; - - const onMouseUp = (evt: any) => { - isLeftMouseDown = false; - if (evt.button === 0 && !drag) { - raycaster.setFromCamera(pointer, camera); - const intersects = raycaster.intersectObjects(scene.children, true).filter(intersect => !intersect.object.name.includes("Roof") && !intersect.object.name.includes("MeasurementReference") && !(intersect.object.type === "GridHelper")); - - if (intersects.length > 0) { - const intersectionPoint = intersects[0].point.clone(); - if (points.length < 2) { - setPoints([...points, intersectionPoint]); - } else { - setPoints([intersectionPoint]); - } - } - } - }; - - const onMouseMove = () => { - if (isLeftMouseDown) drag = true; - }; - - const onContextMenu = (evt: any) => { - evt.preventDefault(); - if (!drag) { - evt.preventDefault(); - setPoints([]); - setTubeGeometry(null); - } - }; - - if (toolMode === "MeasurementScale") { - canvasElement.addEventListener("pointerdown", onMouseDown); - canvasElement.addEventListener("pointermove", onMouseMove); - canvasElement.addEventListener("pointerup", onMouseUp); - canvasElement.addEventListener("contextmenu", onContextMenu); - } else { - resetMeasurement(); - setPoints([]); - } - - return () => { - canvasElement.removeEventListener("pointerdown", onMouseDown); - canvasElement.removeEventListener("pointermove", onMouseMove); - canvasElement.removeEventListener("pointerup", onMouseUp); - canvasElement.removeEventListener("contextmenu", onContextMenu); - }; - }, [toolMode, camera, raycaster, pointer, scene, points]); - - useFrame(() => { - if (points.length === 1) { - raycaster.setFromCamera(pointer, camera); - const intersects = raycaster.intersectObjects(scene.children, true).filter(intersect => !intersect.object.name.includes("Roof") && !intersect.object.name.includes("MeasurementReference") && !(intersect.object.type === "GridHelper")); - - if (intersects.length > 0) { - updateMeasurement(points[0], intersects[0].point); - } - } else if (points.length === 2) { - updateMeasurement(points[0], points[1]); - } else { - resetMeasurement(); - } - }); - - const updateMeasurement = (start: THREE.Vector3, end: THREE.Vector3) => { - const distance = start.distanceTo(end); - - const radius = THREE.MathUtils.clamp(distance * 0.02, MIN_RADIUS, MAX_RADIUS); - const coneRadius = THREE.MathUtils.clamp(distance * 0.05, MIN_CONE_RADIUS, MAX_CONE_RADIUS); - const coneHeight = THREE.MathUtils.clamp(distance * 0.2, MIN_CONE_HEIGHT, MAX_CONE_HEIGHT); - - setConeSize({ radius: coneRadius, height: coneHeight }); - - const direction = new THREE.Vector3().subVectors(end, start).normalize(); - - const offset = direction.clone().multiplyScalar(coneHeight * 0.5); - - let tubeStart = start.clone().add(offset); - let tubeEnd = end.clone().sub(offset); - - tubeStart.y = Math.max(tubeStart.y, 0); - tubeEnd.y = Math.max(tubeEnd.y, 0); - - const curve = new THREE.CatmullRomCurve3([tubeStart, tubeEnd]); - setTubeGeometry(new THREE.TubeGeometry(curve, 20, radius, 8, false)); - - setStartConePosition(tubeStart); - setEndConePosition(tubeEnd); - setStartConeQuaternion(getArrowOrientation(start, end)); - setEndConeQuaternion(getArrowOrientation(end, start)); - }; - - const resetMeasurement = () => { - setTubeGeometry(null); - setStartConePosition(null); - setEndConePosition(null); - }; - - const getArrowOrientation = (start: THREE.Vector3, end: THREE.Vector3) => { - const direction = new THREE.Vector3().subVectors(end, start).normalize().negate(); - const quaternion = new THREE.Quaternion(); - quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), direction); - return quaternion; - }; - - useEffect(() => { - if (points.length === 2) { - console.log(points[0].distanceTo(points[1])); - } - }, [points]) - - return ( - - {startConePosition && ( - - - - - )} - {endConePosition && ( - - - - - )} - {tubeGeometry && ( - - - - )} - - {startConePosition && endConePosition && ( - -
{startConePosition.distanceTo(endConePosition).toFixed(2)} m
- - )} -
- ); - -}; - -export default MeasurementTool; +import * as THREE from 'three'; +import { useEffect, useRef, useState } from 'react'; +import { useThree, useFrame } from '@react-three/fiber'; +import { useToolMode } from '../../../store/store'; +import { Html } from '@react-three/drei'; + +const MeasurementTool = () => { + const { gl, raycaster, pointer, camera, scene } = useThree(); + const { toolMode } = useToolMode(); + + const [points, setPoints] = useState([]); + const [tubeGeometry, setTubeGeometry] = useState(null); + const groupRef = useRef(null); + const [startConePosition, setStartConePosition] = useState(null); + const [endConePosition, setEndConePosition] = useState(null); + const [startConeQuaternion, setStartConeQuaternion] = useState(new THREE.Quaternion()); + const [endConeQuaternion, setEndConeQuaternion] = useState(new THREE.Quaternion()); + const [coneSize, setConeSize] = useState({ radius: 0.2, height: 0.5 }); + + + const MIN_RADIUS = 0.001, MAX_RADIUS = 0.1; + const MIN_CONE_RADIUS = 0.01, MAX_CONE_RADIUS = 0.4; + const MIN_CONE_HEIGHT = 0.035, MAX_CONE_HEIGHT = 2.0; + + useEffect(() => { + const canvasElement = gl.domElement; + let drag = false; + let isLeftMouseDown = false; + + const onMouseDown = () => { + isLeftMouseDown = true; + drag = false; + }; + + const onMouseUp = (evt: any) => { + isLeftMouseDown = false; + if (evt.button === 0 && !drag) { + raycaster.setFromCamera(pointer, camera); + const intersects = raycaster.intersectObjects(scene.children, true).filter(intersect => !intersect.object.name.includes("Roof") && !intersect.object.name.includes("MeasurementReference") && !(intersect.object.type === "GridHelper")); + + if (intersects.length > 0) { + const intersectionPoint = intersects[0].point.clone(); + if (points.length < 2) { + setPoints([...points, intersectionPoint]); + } else { + setPoints([intersectionPoint]); + } + } + } + }; + + const onMouseMove = () => { + if (isLeftMouseDown) drag = true; + }; + + const onContextMenu = (evt: any) => { + evt.preventDefault(); + if (!drag) { + evt.preventDefault(); + setPoints([]); + setTubeGeometry(null); + } + }; + + if (toolMode === "MeasurementScale") { + canvasElement.addEventListener("pointerdown", onMouseDown); + canvasElement.addEventListener("pointermove", onMouseMove); + canvasElement.addEventListener("pointerup", onMouseUp); + canvasElement.addEventListener("contextmenu", onContextMenu); + } else { + resetMeasurement(); + setPoints([]); + } + + return () => { + canvasElement.removeEventListener("pointerdown", onMouseDown); + canvasElement.removeEventListener("pointermove", onMouseMove); + canvasElement.removeEventListener("pointerup", onMouseUp); + canvasElement.removeEventListener("contextmenu", onContextMenu); + }; + }, [toolMode, camera, raycaster, pointer, scene, points]); + + useFrame(() => { + if (points.length === 1) { + raycaster.setFromCamera(pointer, camera); + const intersects = raycaster.intersectObjects(scene.children, true).filter(intersect => !intersect.object.name.includes("Roof") && !intersect.object.name.includes("MeasurementReference") && !(intersect.object.type === "GridHelper")); + + if (intersects.length > 0) { + updateMeasurement(points[0], intersects[0].point); + } + } else if (points.length === 2) { + updateMeasurement(points[0], points[1]); + } else { + resetMeasurement(); + } + }); + + const updateMeasurement = (start: THREE.Vector3, end: THREE.Vector3) => { + const distance = start.distanceTo(end); + + const radius = THREE.MathUtils.clamp(distance * 0.02, MIN_RADIUS, MAX_RADIUS); + const coneRadius = THREE.MathUtils.clamp(distance * 0.05, MIN_CONE_RADIUS, MAX_CONE_RADIUS); + const coneHeight = THREE.MathUtils.clamp(distance * 0.2, MIN_CONE_HEIGHT, MAX_CONE_HEIGHT); + + setConeSize({ radius: coneRadius, height: coneHeight }); + + const direction = new THREE.Vector3().subVectors(end, start).normalize(); + + const offset = direction.clone().multiplyScalar(coneHeight * 0.5); + + let tubeStart = start.clone().add(offset); + let tubeEnd = end.clone().sub(offset); + + tubeStart.y = Math.max(tubeStart.y, 0); + tubeEnd.y = Math.max(tubeEnd.y, 0); + + const curve = new THREE.CatmullRomCurve3([tubeStart, tubeEnd]); + setTubeGeometry(new THREE.TubeGeometry(curve, 20, radius, 8, false)); + + setStartConePosition(tubeStart); + setEndConePosition(tubeEnd); + setStartConeQuaternion(getArrowOrientation(start, end)); + setEndConeQuaternion(getArrowOrientation(end, start)); + }; + + const resetMeasurement = () => { + setTubeGeometry(null); + setStartConePosition(null); + setEndConePosition(null); + }; + + const getArrowOrientation = (start: THREE.Vector3, end: THREE.Vector3) => { + const direction = new THREE.Vector3().subVectors(end, start).normalize().negate(); + const quaternion = new THREE.Quaternion(); + quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), direction); + return quaternion; + }; + + useEffect(() => { + if (points.length === 2) { + console.log(points[0].distanceTo(points[1])); + } + }, [points]) + + return ( + + {startConePosition && ( + + + + + )} + {endConePosition && ( + + + + + )} + {tubeGeometry && ( + + + + )} + + {startConePosition && endConePosition && ( + +
{startConePosition.distanceTo(endConePosition).toFixed(2)} m
+ + )} +
+ ); + +}; + +export default MeasurementTool; diff --git a/app/src/modules/scene/world/world.tsx b/app/src/modules/scene/world/world.tsx index b83fa1c..f8a43ec 100644 --- a/app/src/modules/scene/world/world.tsx +++ b/app/src/modules/scene/world/world.tsx @@ -1,336 +1,336 @@ -////////// Three and React Three Fiber Imports ////////// - -import * as THREE from "three"; -import { useEffect, useRef, useState } from "react"; -import { useThree, useFrame } from "@react-three/fiber"; - -////////// Component Imports ////////// - -import DistanceText from "../../builder/geomentries/lines/distanceText"; -import ReferenceDistanceText from "../../builder/geomentries/lines/referenceDistanceText"; - -////////// Assests Imports ////////// - -import arch from "../../../assets/gltf-glb/arch.glb"; -import door from "../../../assets/gltf-glb/door.glb"; -import Window from "../../../assets/gltf-glb/window.glb"; - -////////// Zustand State Imports ////////// - -import { - useToggleView, - useDeletePointOrLine, - useMovePoint, - useActiveLayer, - useSocketStore, - useWallVisibility, - useRoofVisibility, - useShadows, - useUpdateScene, - useWalls, - useToolMode -} from "../../../store/store"; - -////////// 3D Function Imports ////////// - -import loadWalls from "../../builder/geomentries/walls/loadWalls"; - -import * as Types from "../../../types/world/worldTypes"; - -import SocketResponses from "../../collaboration/socketResponses.dev"; -import FloorItemsGroup from "../../builder/groups/floorItemsGroup"; -import FloorPlanGroup from "../../builder/groups/floorPlanGroup"; -import FloorGroup from "../../builder/groups/floorGroup"; -import FloorGroupAilse from "../../builder/groups/floorGroupAisle"; -import Draw from "../../builder/functions/draw"; -import WallsAndWallItems from "../../builder/groups/wallsAndWallItems"; -import Ground from "../environment/ground"; -// import ZoneGroup from "../groups/zoneGroup1"; -import { findEnvironment } from "../../../services/factoryBuilder/environment/findEnvironment"; -import Layer2DVisibility from "../../builder/geomentries/layers/layer2DVisibility"; -import DrieHtmlTemp from "../mqttTemp/drieHtmlTemp"; -import ZoneGroup from "../../builder/groups/zoneGroup"; - -export default function World() { - const state = useThree(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements. - const csg = useRef(); // Reference for CSG object, used for 3D modeling. - const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects. - const scene = useRef() as Types.RefScene; // Reference to the scene. - const camera = useRef() as Types.RefCamera; // Reference to the camera object. - const controls = useRef(); // Reference to the controls object. - const raycaster = useRef() as Types.RefRaycaster; // Reference for raycaster used for detecting objects being pointed at in the scene. - const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control. - - // Assigning the scene and camera from the Three.js state to the references. - - scene.current = state.scene; - camera.current = state.camera; - controls.current = state.controls; - raycaster.current = state.raycaster; - - const plane = useRef(null); // Reference for a plane object for raycaster reference. - const grid = useRef() as any; // Reference for a grid object for raycaster reference. - const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line. - const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end). - const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc... - const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active. - const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point. - const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start). - const tempLoader = useRef() as Types.RefMesh; // Reference for a temporary loader for the floor items. - const isTempLoader = useRef() as Types.RefBoolean; // Reference to check if a temporary loader is active. - const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation. - const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn. - const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn. - const onlyFloorline = useRef([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn. - const onlyFloorlines = useRef([]); // Reference for all the floor lines that are ever drawn. - const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw. - const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not. - const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed. - const itemsGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the floor items (Gltf). - const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors. - const AttachedObject = useRef() as Types.RefMesh; // Reference for an object that is attached using dbl click for transform controls rotation. - const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group. - const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn. - const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created. - const floorGroupAisle = useRef() as Types.RefGroup; - const zoneGroup = useRef() as Types.RefGroup; - const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls. - const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted. - const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted. - const hoveredDeletableFloorItem = useRef() as Types.RefMesh; // Reference for the currently hovered floor item that can be deleted. - const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted. - const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted. - const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc... - - const cursorPosition = new THREE.Vector3(); // 3D vector for storing the cursor position. - - const [selectedItemsIndex, setSelectedItemsIndex] = useState(null); // State for tracking the index of the selected item. - const { activeLayer, setActiveLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx. - const { toggleView, setToggleView } = useToggleView(); // State for toggling between 2D and 3D. - const { toolMode, setToolMode } = useToolMode(); - const { movePoint, setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not. - const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); - const { socket } = useSocketStore(); - const { roofVisibility, setRoofVisibility } = useRoofVisibility(); - const { wallVisibility, setWallVisibility } = useWallVisibility(); - const { shadows, setShadows } = useShadows(); - const { updateScene, setUpdateScene } = useUpdateScene(); - const { walls, setWalls } = useWalls(); - const [RefTextupdate, setRefTextUpdate] = useState(-1000); - - - // const loader = new GLTFLoader(); - // const dracoLoader = new DRACOLoader(); - - // dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); - // loader.setDRACOLoader(dracoLoader); - - ////////// Assest Configuration Values ////////// - - const AssetConfigurations: Types.AssetConfigurations = { - arch: { - modelUrl: arch, - scale: [0.75, 0.75, 0.75], - csgscale: [2, 4, 0.5], - csgposition: [0, 2, 0], - positionY: () => 0, - type: "Fixed-Move", - }, - door: { - modelUrl: door, - scale: [0.75, 0.75, 0.75], - csgscale: [2, 4, 0.5], - csgposition: [0, 2, 0], - positionY: () => 0, - type: "Fixed-Move", - }, - window: { - modelUrl: Window, - scale: [0.75, 0.75, 0.75], - csgscale: [5, 3, 0.5], - csgposition: [0, 1.5, 0], - positionY: (intersectionPoint) => intersectionPoint.point.y, - type: "Free-Move", - }, - }; - - ////////// All Toggle's ////////// - - useEffect(() => { - setRefTextUpdate((prevUpdate) => prevUpdate - 1); - if (dragPointControls.current) { - dragPointControls.current.enabled = false; - } - if (toggleView) { - Layer2DVisibility(activeLayer, floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, currentLayerPoint, dragPointControls); - } else { - setToolMode(null); - setDeletePointOrLine(false); - setMovePoint(false); - loadWalls(lines, setWalls); - setUpdateScene(true); - line.current = []; - } - }, [toggleView]); - - useEffect(() => { - THREE.Cache.clear(); - THREE.Cache.enabled = true; - }, []); - - useEffect(() => { - const email = localStorage.getItem('email') - const organization = (email!.split("@")[1]).split(".")[0]; - - async function fetchVisibility() { - const visibility = await findEnvironment(organization, localStorage.getItem('userId')!); - if (visibility) { - setRoofVisibility(visibility.roofVisibility); - setWallVisibility(visibility.wallVisibility); - setShadows(visibility.shadowVisibility); - } - } - fetchVisibility(); - }, []) - - ////////// UseFrame is Here ////////// - - useFrame(() => { - if (toolMode) { - Draw(state, plane, cursorPosition, floorPlanGroupPoint, floorPlanGroupLine, snappedPoint, isSnapped, isSnappedUUID, line, lines, ispreSnapped, floorPlanGroup, ReferenceLineMesh, LineCreated, setRefTextUpdate, Tube, anglesnappedPoint, isAngleSnapped, toolMode) - } - }); - - ////////// Return ////////// - - return ( - <> - - - - - - - - - - - - - - - - - {/* */} - - - - - - - - - - ); +////////// Three and React Three Fiber Imports ////////// + +import * as THREE from "three"; +import { useEffect, useRef, useState } from "react"; +import { useThree, useFrame } from "@react-three/fiber"; + +////////// Component Imports ////////// + +import DistanceText from "../../builder/geomentries/lines/distanceText"; +import ReferenceDistanceText from "../../builder/geomentries/lines/referenceDistanceText"; + +////////// Assests Imports ////////// + +import arch from "../../../assets/gltf-glb/arch.glb"; +import door from "../../../assets/gltf-glb/door.glb"; +import Window from "../../../assets/gltf-glb/window.glb"; + +////////// Zustand State Imports ////////// + +import { + useToggleView, + useDeletePointOrLine, + useMovePoint, + useActiveLayer, + useSocketStore, + useWallVisibility, + useRoofVisibility, + useShadows, + useUpdateScene, + useWalls, + useToolMode +} from "../../../store/store"; + +////////// 3D Function Imports ////////// + +import loadWalls from "../../builder/geomentries/walls/loadWalls"; + +import * as Types from "../../../types/world/worldTypes"; + +import SocketResponses from "../../collaboration/socketResponses.dev"; +import FloorItemsGroup from "../../builder/groups/floorItemsGroup"; +import FloorPlanGroup from "../../builder/groups/floorPlanGroup"; +import FloorGroup from "../../builder/groups/floorGroup"; +import FloorGroupAilse from "../../builder/groups/floorGroupAisle"; +import Draw from "../../builder/functions/draw"; +import WallsAndWallItems from "../../builder/groups/wallsAndWallItems"; +import Ground from "../environment/ground"; +// import ZoneGroup from "../groups/zoneGroup1"; +import { findEnvironment } from "../../../services/factoryBuilder/environment/findEnvironment"; +import Layer2DVisibility from "../../builder/geomentries/layers/layer2DVisibility"; +import DrieHtmlTemp from "../mqttTemp/drieHtmlTemp"; +import ZoneGroup from "../../builder/groups/zoneGroup"; + +export default function World() { + const state = useThree(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements. + const csg = useRef(); // Reference for CSG object, used for 3D modeling. + const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects. + const scene = useRef() as Types.RefScene; // Reference to the scene. + const camera = useRef() as Types.RefCamera; // Reference to the camera object. + const controls = useRef(); // Reference to the controls object. + const raycaster = useRef() as Types.RefRaycaster; // Reference for raycaster used for detecting objects being pointed at in the scene. + const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control. + + // Assigning the scene and camera from the Three.js state to the references. + + scene.current = state.scene; + camera.current = state.camera; + controls.current = state.controls; + raycaster.current = state.raycaster; + + const plane = useRef(null); // Reference for a plane object for raycaster reference. + const grid = useRef() as any; // Reference for a grid object for raycaster reference. + const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line. + const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end). + const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc... + const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active. + const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point. + const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start). + const tempLoader = useRef() as Types.RefMesh; // Reference for a temporary loader for the floor items. + const isTempLoader = useRef() as Types.RefBoolean; // Reference to check if a temporary loader is active. + const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation. + const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn. + const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn. + const onlyFloorline = useRef([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn. + const onlyFloorlines = useRef([]); // Reference for all the floor lines that are ever drawn. + const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw. + const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not. + const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed. + const itemsGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the floor items (Gltf). + const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors. + const AttachedObject = useRef() as Types.RefMesh; // Reference for an object that is attached using dbl click for transform controls rotation. + const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group. + const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn. + const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created. + const floorGroupAisle = useRef() as Types.RefGroup; + const zoneGroup = useRef() as Types.RefGroup; + const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls. + const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted. + const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted. + const hoveredDeletableFloorItem = useRef() as Types.RefMesh; // Reference for the currently hovered floor item that can be deleted. + const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted. + const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted. + const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc... + + const cursorPosition = new THREE.Vector3(); // 3D vector for storing the cursor position. + + const [selectedItemsIndex, setSelectedItemsIndex] = useState(null); // State for tracking the index of the selected item. + const { activeLayer, setActiveLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx. + const { toggleView, setToggleView } = useToggleView(); // State for toggling between 2D and 3D. + const { toolMode, setToolMode } = useToolMode(); + const { movePoint, setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not. + const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); + const { socket } = useSocketStore(); + const { roofVisibility, setRoofVisibility } = useRoofVisibility(); + const { wallVisibility, setWallVisibility } = useWallVisibility(); + const { shadows, setShadows } = useShadows(); + const { updateScene, setUpdateScene } = useUpdateScene(); + const { walls, setWalls } = useWalls(); + const [RefTextupdate, setRefTextUpdate] = useState(-1000); + + + // const loader = new GLTFLoader(); + // const dracoLoader = new DRACOLoader(); + + // dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); + // loader.setDRACOLoader(dracoLoader); + + ////////// Assest Configuration Values ////////// + + const AssetConfigurations: Types.AssetConfigurations = { + arch: { + modelUrl: arch, + scale: [0.75, 0.75, 0.75], + csgscale: [2, 4, 0.5], + csgposition: [0, 2, 0], + positionY: () => 0, + type: "Fixed-Move", + }, + door: { + modelUrl: door, + scale: [0.75, 0.75, 0.75], + csgscale: [2, 4, 0.5], + csgposition: [0, 2, 0], + positionY: () => 0, + type: "Fixed-Move", + }, + window: { + modelUrl: Window, + scale: [0.75, 0.75, 0.75], + csgscale: [5, 3, 0.5], + csgposition: [0, 1.5, 0], + positionY: (intersectionPoint) => intersectionPoint.point.y, + type: "Free-Move", + }, + }; + + ////////// All Toggle's ////////// + + useEffect(() => { + setRefTextUpdate((prevUpdate) => prevUpdate - 1); + if (dragPointControls.current) { + dragPointControls.current.enabled = false; + } + if (toggleView) { + Layer2DVisibility(activeLayer, floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, currentLayerPoint, dragPointControls); + } else { + setToolMode(null); + setDeletePointOrLine(false); + setMovePoint(false); + loadWalls(lines, setWalls); + setUpdateScene(true); + line.current = []; + } + }, [toggleView]); + + useEffect(() => { + THREE.Cache.clear(); + THREE.Cache.enabled = true; + }, []); + + useEffect(() => { + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + async function fetchVisibility() { + const visibility = await findEnvironment(organization, localStorage.getItem('userId')!); + if (visibility) { + setRoofVisibility(visibility.roofVisibility); + setWallVisibility(visibility.wallVisibility); + setShadows(visibility.shadowVisibility); + } + } + fetchVisibility(); + }, []) + + ////////// UseFrame is Here ////////// + + useFrame(() => { + if (toolMode) { + Draw(state, plane, cursorPosition, floorPlanGroupPoint, floorPlanGroupLine, snappedPoint, isSnapped, isSnappedUUID, line, lines, ispreSnapped, floorPlanGroup, ReferenceLineMesh, LineCreated, setRefTextUpdate, Tube, anglesnappedPoint, isAngleSnapped, toolMode) + } + }); + + ////////// Return ////////// + + return ( + <> + + + + + + + + + + + + + + + + + {/* */} + + + + + + + + + + ); } \ No newline at end of file diff --git a/app/src/modules/simulation/behaviour/behaviour.tsx b/app/src/modules/simulation/behaviour/behaviour.tsx index f0289f9..f7484f3 100644 --- a/app/src/modules/simulation/behaviour/behaviour.tsx +++ b/app/src/modules/simulation/behaviour/behaviour.tsx @@ -1,77 +1,79 @@ -import { useFloorItems } from '../../../store/store'; -import * as THREE from 'three'; -import * as Types from '../../../types/world/worldTypes'; -import { useEffect } from 'react'; - - -interface Path { - modeluuid: string; - points: { - uuid: string; - position: [number, number, number]; - rotation: [number, number, number]; - events: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; - triggers: { uuid: string; type: string; isUsed: boolean }[] | []; - }[]; - pathPosition: [number, number, number]; - pathRotation: [number, number, number]; - speed: number; -} - -function Behaviour({ setSimulationPaths }: { setSimulationPaths: any }) { - const { floorItems } = useFloorItems(); - - useEffect(() => { - const newPaths: Path[] = []; - - floorItems.forEach((item: Types.FloorItemType) => { - if (item.modelfileID === "6633215057b31fe671145959") { - const point1Position = new THREE.Vector3(0, 1.25, 3.3); - const middlePointPosition = new THREE.Vector3(0, 1.25, 0); - const point2Position = new THREE.Vector3(0, 1.25, -3.3); - - const point1UUID = THREE.MathUtils.generateUUID(); - const point2UUID = THREE.MathUtils.generateUUID(); - const middlePointUUID = THREE.MathUtils.generateUUID(); - - const newPath: Path = { - modeluuid: item.modeluuid, - points: [ - { - uuid: point1UUID, - position: [point1Position.x, point1Position.y, point1Position.z], - rotation: [0, 0, 0], - events: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], - triggers: [], - }, - { - uuid: middlePointUUID, - position: [middlePointPosition.x, middlePointPosition.y, middlePointPosition.z], - rotation: [0, 0, 0], - events: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], - triggers: [], - }, - { - uuid: point2UUID, - position: [point2Position.x, point2Position.y, point2Position.z], - rotation: [0, 0, 0], - events: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], - triggers: [], - }, - ], - pathPosition: [...item.position], - pathRotation: [item.rotation.x, item.rotation.y, item.rotation.z], - speed: 1, - }; - - newPaths.push(newPath); - } - }); - - setSimulationPaths(newPaths); - }, [floorItems]); - - return null; -} - -export default Behaviour; +import { useFloorItems } from '../../../store/store'; +import * as THREE from 'three'; +import * as Types from '../../../types/world/worldTypes'; +import { useEffect } from 'react'; + + +interface Path { + modeluuid: string; + modelName: string; + points: { + uuid: string; + position: [number, number, number]; + rotation: [number, number, number]; + actions: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; + triggers: { uuid: string; type: string; isUsed: boolean }[] | []; + }[]; + pathPosition: [number, number, number]; + pathRotation: [number, number, number]; + speed: number; +} + +function Behaviour({ setSimulationPaths }: { setSimulationPaths: any }) { + const { floorItems } = useFloorItems(); + + useEffect(() => { + const newPaths: Path[] = []; + + floorItems.forEach((item: Types.FloorItemType) => { + if (item.modelfileID === "6633215057b31fe671145959") { + const point1Position = new THREE.Vector3(0, 1.25, 3.3); + const middlePointPosition = new THREE.Vector3(0, 1.25, 0); + const point2Position = new THREE.Vector3(0, 1.25, -3.3); + + const point1UUID = THREE.MathUtils.generateUUID(); + const point2UUID = THREE.MathUtils.generateUUID(); + const middlePointUUID = THREE.MathUtils.generateUUID(); + + const newPath: Path = { + modeluuid: item.modeluuid, + modelName: item.modelname, + points: [ + { + uuid: point1UUID, + position: [point1Position.x, point1Position.y, point1Position.z], + rotation: [0, 0, 0], + actions: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], + triggers: [], + }, + { + uuid: middlePointUUID, + position: [middlePointPosition.x, middlePointPosition.y, middlePointPosition.z], + rotation: [0, 0, 0], + actions: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], + triggers: [], + }, + { + uuid: point2UUID, + position: [point2Position.x, point2Position.y, point2Position.z], + rotation: [0, 0, 0], + actions: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], + triggers: [], + }, + ], + pathPosition: [...item.position], + pathRotation: [item.rotation.x, item.rotation.y, item.rotation.z], + speed: 1, + }; + + newPaths.push(newPath); + } + }); + + setSimulationPaths(newPaths); + }, [floorItems]); + + return null; +} + +export default Behaviour; diff --git a/app/src/modules/simulation/events.tsx/eventsControl.tsx b/app/src/modules/simulation/events.tsx/eventsControl.tsx deleted file mode 100644 index 4f273a2..0000000 --- a/app/src/modules/simulation/events.tsx/eventsControl.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useControls } from 'leva'; -import { useSelectedEventSphere } from '../../../store/store'; - -interface Path { - modeluuid: string; - points: { - uuid: string; - position: [number, number, number]; - rotation: [number, number, number]; - events: string; - triggers: string; - }[]; - position: [number, number, number]; - rotation: [number, number, number]; -} - -const EventsControl = ({ simulationPaths, setSimulationPaths }: { simulationPaths: Path[], setSimulationPaths: any }) => { - const { selectedEventSphere, setSelectedEventSphere } = useSelectedEventSphere(); - - const { events, triggers }: any = useControls({ - events: { - value: selectedEventSphere?.point?.userData?.events || '', - options: ['Event1', 'Event2', 'Event3'], - onChange: (newEvent: string) => updatePathData(newEvent, 'events') - }, - triggers: { - value: selectedEventSphere?.point?.userData?.triggers || '', - options: ['None', 'Trigger1', 'Trigger2', 'Trigger3'], - onChange: (newTrigger: string) => updatePathData(newTrigger, 'triggers') - }, - }); - - function updatePathData(value: string, key: 'events' | 'triggers') { - if (!selectedEventSphere) return; - - const updatedPaths = simulationPaths.map((path) => - path.modeluuid === selectedEventSphere.path.modeluuid - ? { - ...path, - points: path.points.map((point) => - point.uuid === selectedEventSphere.point.uuid - ? { ...point, [key]: value } - : point - ), - } - : path - ); - console.log('updatedPaths: ', updatedPaths); - setSimulationPaths(updatedPaths); - } - - return null; -}; - -export default EventsControl; diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx index c8ab607..03724d5 100644 --- a/app/src/modules/simulation/path/pathConnector.tsx +++ b/app/src/modules/simulation/path/pathConnector.tsx @@ -1,287 +1,287 @@ -import { useFrame, useThree } from '@react-three/fiber'; -import React, { useEffect, useState } from 'react'; -import * as THREE from 'three'; -import { QuadraticBezierLine } from '@react-three/drei'; -import { useConnections, useIsConnecting, useSimulationPaths } from '../../../store/store'; -import useModuleStore from '../../../store/useModuleStore'; - -function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject }) { - const { activeModule } = useModuleStore(); - const { gl, raycaster, scene, pointer, camera } = useThree(); - const { connections, setConnections, addConnection } = useConnections(); - const { isConnecting, setIsConnecting } = useIsConnecting(); - const { simulationPaths, setSimulationPaths } = useSimulationPaths(); - - const [firstSelected, setFirstSelected] = useState<{ pathUUID: string; sphereUUID: string; position: THREE.Vector3; isCorner: boolean; } | null>(null); - const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3, end: THREE.Vector3, mid: THREE.Vector3 } | null>(null); - const [hoveredSphere, setHoveredSphere] = useState<{ sphereUUID: string, position: THREE.Vector3 } | null>(null); - const [helperlineColor, setHelperLineColor] = useState('red'); - - useEffect(() => { - const canvasElement = gl.domElement; - let drag = false; - let MouseDown = false; - - const onMouseDown = () => { - MouseDown = true; - drag = false; - }; - - const onMouseUp = () => { - MouseDown = false; - }; - - const onMouseMove = () => { - if (MouseDown) { - drag = true; - } - }; - - const onContextMenu = (evt: MouseEvent) => { - evt.preventDefault(); - if (drag || evt.button === 0) return; - - raycaster.setFromCamera(pointer, camera); - const intersects = raycaster.intersectObjects(pathsGroupRef.current.children, true); - - if (intersects.length > 0) { - const intersected = intersects[0].object; - - if (intersected.name.includes("event-sphere")) { - const pathUUID = intersected.userData.path.modeluuid; - const sphereUUID = intersected.uuid; - const worldPosition = new THREE.Vector3(); - intersected.getWorldPosition(worldPosition); - - const isStartOrEnd = intersected.userData.path.points.length > 0 && ( - sphereUUID === intersected.userData.path.points[0].uuid || - sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid - ); - - if (pathUUID) { - const isAlreadyConnected = connections.some((connection) => - connection.fromUUID === sphereUUID || - connection.toConnections.some(conn => conn.toUUID === sphereUUID) - ); - - if (isAlreadyConnected) { - console.log("Sphere is already connected. Ignoring."); - return; - } - - if (!firstSelected) { - setFirstSelected({ - pathUUID, - sphereUUID, - position: worldPosition, - isCorner: isStartOrEnd - }); - setIsConnecting(true); - } else { - if (firstSelected.sphereUUID === sphereUUID) return; - - if (firstSelected.pathUUID === pathUUID) { - console.log("Cannot connect spheres on the same path."); - return; - } - if (!firstSelected.isCorner && !isStartOrEnd) { - console.log("At least one of the selected spheres must be a start or end point."); - return; - } - - addConnection({ - fromPathUUID: firstSelected.pathUUID, - fromUUID: firstSelected.sphereUUID, - toConnections: [{ toPathUUID: pathUUID, toUUID: sphereUUID }] - }); - - setFirstSelected(null); - setCurrentLine(null); - setIsConnecting(false); - setHoveredSphere(null); - } - } - } - } else { - setFirstSelected(null); - setCurrentLine(null); - setIsConnecting(false); - setHoveredSphere(null); - } - }; - - if (activeModule === 'simulation') { - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - canvasElement.addEventListener("contextmenu", onContextMenu); - } else { - setFirstSelected(null); - setCurrentLine(null); - setIsConnecting(false); - setHoveredSphere(null); - } - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - canvasElement.removeEventListener("contextmenu", onContextMenu); - }; - }, [camera, scene, raycaster, firstSelected, connections]); - - useFrame(() => { - if (firstSelected) { - raycaster.setFromCamera(pointer, camera); - const intersects = raycaster.intersectObjects(scene.children, true).filter((intersect) => - !intersect.object.name.includes("Roof") && - !intersect.object.name.includes("MeasurementReference") && - !intersect.object.userData.isPathObject && - !(intersect.object.type === "GridHelper") - ); - - let point: THREE.Vector3 | null = null; - let snappedSphere: { sphereUUID: string, position: THREE.Vector3, pathUUID: string, isCorner: boolean } | null = null; - let isInvalidConnection = false; - - if (intersects.length > 0) { - point = intersects[0].point; - - if (point.y < 0.05) { - point = new THREE.Vector3(point.x, 0.05, point.z); - } - } - - const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) => - obj.object.name.includes("event-sphere") - ); - - if (sphereIntersects.length > 0) { - const sphere = sphereIntersects[0].object; - const sphereUUID = sphere.uuid; - const spherePosition = new THREE.Vector3(); - sphere.getWorldPosition(spherePosition); - const pathUUID = sphere.userData.path.modeluuid; - - const isStartOrEnd = sphere.userData.path.points.length > 0 && ( - sphereUUID === sphere.userData.path.points[0].uuid || - sphereUUID === sphere.userData.path.points[sphere.userData.path.points.length - 1].uuid - ); - - const isAlreadyConnected = connections.some((connection) => - connection.fromUUID === sphereUUID || - connection.toConnections.some(conn => conn.toUUID === sphereUUID) - ); - - if ( - !isAlreadyConnected && - firstSelected.sphereUUID !== sphereUUID && - firstSelected.pathUUID !== pathUUID && - (firstSelected.isCorner || isStartOrEnd) - ) { - snappedSphere = { sphereUUID, position: spherePosition, pathUUID, isCorner: isStartOrEnd }; - } else { - isInvalidConnection = true; - } - } - - if (snappedSphere) { - setHoveredSphere(snappedSphere); - point = snappedSphere.position; - } else { - setHoveredSphere(null); - } - - if (point) { - const distance = firstSelected.position.distanceTo(point); - const heightFactor = Math.max(0.5, distance * 0.2); - const midPoint = new THREE.Vector3( - (firstSelected.position.x + point.x) / 2, - Math.max(firstSelected.position.y, point.y) + heightFactor, - (firstSelected.position.z + point.z) / 2 - ); - - setCurrentLine({ - start: firstSelected.position, - end: point, - mid: midPoint, - }); - - setIsConnecting(true); - - if (sphereIntersects.length > 0) { - setHelperLineColor(isInvalidConnection ? 'red' : '#6cf542'); - } else { - setHelperLineColor('yellow'); - } - } else { - setCurrentLine(null); - setIsConnecting(false); - } - } else { - setCurrentLine(null); - setIsConnecting(false); - } - }); - - - useEffect(() => { - console.log('connections: ', connections); - }, [connections]); - - return ( - <> - {connections.map((connection, index) => { - const fromSphere = scene.getObjectByProperty('uuid', connection.fromUUID); - const toSphere = scene.getObjectByProperty('uuid', connection.toConnections[0].toUUID); - - if (fromSphere && toSphere) { - const fromWorldPosition = new THREE.Vector3(); - const toWorldPosition = new THREE.Vector3(); - fromSphere.getWorldPosition(fromWorldPosition); - toSphere.getWorldPosition(toWorldPosition); - - const distance = fromWorldPosition.distanceTo(toWorldPosition); - const heightFactor = Math.max(0.5, distance * 0.2); - - const midPoint = new THREE.Vector3( - (fromWorldPosition.x + toWorldPosition.x) / 2, - Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, - (fromWorldPosition.z + toWorldPosition.z) / 2 - ); - - return ( - - ); - } - return null; - })} - - {currentLine && ( - - )} - - ); -} - +import { useFrame, useThree } from '@react-three/fiber'; +import React, { useEffect, useState } from 'react'; +import * as THREE from 'three'; +import { QuadraticBezierLine } from '@react-three/drei'; +import { useConnections, useIsConnecting, useSimulationPaths } from '../../../store/store'; +import useModuleStore from '../../../store/useModuleStore'; + +function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject }) { + const { activeModule } = useModuleStore(); + const { gl, raycaster, scene, pointer, camera } = useThree(); + const { connections, setConnections, addConnection } = useConnections(); + const { isConnecting, setIsConnecting } = useIsConnecting(); + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); + + const [firstSelected, setFirstSelected] = useState<{ pathUUID: string; sphereUUID: string; position: THREE.Vector3; isCorner: boolean; } | null>(null); + const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3, end: THREE.Vector3, mid: THREE.Vector3 } | null>(null); + const [hoveredSphere, setHoveredSphere] = useState<{ sphereUUID: string, position: THREE.Vector3 } | null>(null); + const [helperlineColor, setHelperLineColor] = useState('red'); + + useEffect(() => { + const canvasElement = gl.domElement; + let drag = false; + let MouseDown = false; + + const onMouseDown = () => { + MouseDown = true; + drag = false; + }; + + const onMouseUp = () => { + MouseDown = false; + }; + + const onMouseMove = () => { + if (MouseDown) { + drag = true; + } + }; + + const onContextMenu = (evt: MouseEvent) => { + evt.preventDefault(); + if (drag || evt.button === 0) return; + + raycaster.setFromCamera(pointer, camera); + const intersects = raycaster.intersectObjects(pathsGroupRef.current.children, true); + + if (intersects.length > 0) { + const intersected = intersects[0].object; + + if (intersected.name.includes("event-sphere")) { + const pathUUID = intersected.userData.path.modeluuid; + const sphereUUID = intersected.uuid; + const worldPosition = new THREE.Vector3(); + intersected.getWorldPosition(worldPosition); + + const isStartOrEnd = intersected.userData.path.points.length > 0 && ( + sphereUUID === intersected.userData.path.points[0].uuid || + sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid + ); + + if (pathUUID) { + const isAlreadyConnected = connections.some((connection) => + connection.fromUUID === sphereUUID || + connection.toConnections.some(conn => conn.toUUID === sphereUUID) + ); + + if (isAlreadyConnected) { + console.log("Sphere is already connected. Ignoring."); + return; + } + + if (!firstSelected) { + setFirstSelected({ + pathUUID, + sphereUUID, + position: worldPosition, + isCorner: isStartOrEnd + }); + setIsConnecting(true); + } else { + if (firstSelected.sphereUUID === sphereUUID) return; + + if (firstSelected.pathUUID === pathUUID) { + console.log("Cannot connect spheres on the same path."); + return; + } + if (!firstSelected.isCorner && !isStartOrEnd) { + console.log("At least one of the selected spheres must be a start or end point."); + return; + } + + addConnection({ + fromPathUUID: firstSelected.pathUUID, + fromUUID: firstSelected.sphereUUID, + toConnections: [{ toPathUUID: pathUUID, toUUID: sphereUUID }] + }); + + setFirstSelected(null); + setCurrentLine(null); + setIsConnecting(false); + setHoveredSphere(null); + } + } + } + } else { + setFirstSelected(null); + setCurrentLine(null); + setIsConnecting(false); + setHoveredSphere(null); + } + }; + + if (activeModule === 'simulation') { + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + canvasElement.addEventListener("contextmenu", onContextMenu); + } else { + setFirstSelected(null); + setCurrentLine(null); + setIsConnecting(false); + setHoveredSphere(null); + } + + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + canvasElement.removeEventListener("contextmenu", onContextMenu); + }; + }, [camera, scene, raycaster, firstSelected, connections]); + + useFrame(() => { + if (firstSelected) { + raycaster.setFromCamera(pointer, camera); + const intersects = raycaster.intersectObjects(scene.children, true).filter((intersect) => + !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("MeasurementReference") && + !intersect.object.userData.isPathObject && + !(intersect.object.type === "GridHelper") + ); + + let point: THREE.Vector3 | null = null; + let snappedSphere: { sphereUUID: string, position: THREE.Vector3, pathUUID: string, isCorner: boolean } | null = null; + let isInvalidConnection = false; + + if (intersects.length > 0) { + point = intersects[0].point; + + if (point.y < 0.05) { + point = new THREE.Vector3(point.x, 0.05, point.z); + } + } + + const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) => + obj.object.name.includes("event-sphere") + ); + + if (sphereIntersects.length > 0) { + const sphere = sphereIntersects[0].object; + const sphereUUID = sphere.uuid; + const spherePosition = new THREE.Vector3(); + sphere.getWorldPosition(spherePosition); + const pathUUID = sphere.userData.path.modeluuid; + + const isStartOrEnd = sphere.userData.path.points.length > 0 && ( + sphereUUID === sphere.userData.path.points[0].uuid || + sphereUUID === sphere.userData.path.points[sphere.userData.path.points.length - 1].uuid + ); + + const isAlreadyConnected = connections.some((connection) => + connection.fromUUID === sphereUUID || + connection.toConnections.some(conn => conn.toUUID === sphereUUID) + ); + + if ( + !isAlreadyConnected && + firstSelected.sphereUUID !== sphereUUID && + firstSelected.pathUUID !== pathUUID && + (firstSelected.isCorner || isStartOrEnd) + ) { + snappedSphere = { sphereUUID, position: spherePosition, pathUUID, isCorner: isStartOrEnd }; + } else { + isInvalidConnection = true; + } + } + + if (snappedSphere) { + setHoveredSphere(snappedSphere); + point = snappedSphere.position; + } else { + setHoveredSphere(null); + } + + if (point) { + const distance = firstSelected.position.distanceTo(point); + const heightFactor = Math.max(0.5, distance * 0.2); + const midPoint = new THREE.Vector3( + (firstSelected.position.x + point.x) / 2, + Math.max(firstSelected.position.y, point.y) + heightFactor, + (firstSelected.position.z + point.z) / 2 + ); + + setCurrentLine({ + start: firstSelected.position, + end: point, + mid: midPoint, + }); + + setIsConnecting(true); + + if (sphereIntersects.length > 0) { + setHelperLineColor(isInvalidConnection ? 'red' : '#6cf542'); + } else { + setHelperLineColor('yellow'); + } + } else { + setCurrentLine(null); + setIsConnecting(false); + } + } else { + setCurrentLine(null); + setIsConnecting(false); + } + }); + + + useEffect(() => { + console.log('connections: ', connections); + }, [connections]); + + return ( + <> + {connections.map((connection, index) => { + const fromSphere = scene.getObjectByProperty('uuid', connection.fromUUID); + const toSphere = scene.getObjectByProperty('uuid', connection.toConnections[0].toUUID); + + if (fromSphere && toSphere) { + const fromWorldPosition = new THREE.Vector3(); + const toWorldPosition = new THREE.Vector3(); + fromSphere.getWorldPosition(fromWorldPosition); + toSphere.getWorldPosition(toWorldPosition); + + const distance = fromWorldPosition.distanceTo(toWorldPosition); + const heightFactor = Math.max(0.5, distance * 0.2); + + const midPoint = new THREE.Vector3( + (fromWorldPosition.x + toWorldPosition.x) / 2, + Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, + (fromWorldPosition.z + toWorldPosition.z) / 2 + ); + + return ( + + ); + } + return null; + })} + + {currentLine && ( + + )} + + ); +} + export default PathConnector; \ No newline at end of file diff --git a/app/src/modules/simulation/path/pathCreation.tsx b/app/src/modules/simulation/path/pathCreation.tsx index f79d646..7ff7489 100644 --- a/app/src/modules/simulation/path/pathCreation.tsx +++ b/app/src/modules/simulation/path/pathCreation.tsx @@ -1,163 +1,171 @@ -import * as THREE from 'three'; -import { useRef, useState, useEffect } from 'react'; -import { Sphere, TransformControls } from '@react-three/drei'; -import { useIsConnecting, useRenderDistance, useSelectedEventSphere, useSelectedPath, useSimulationPaths } from '../../../store/store'; -import { useFrame, useThree } from '@react-three/fiber'; - -interface Path { - modeluuid: string; - points: { - uuid: string; - position: [number, number, number]; - rotation: [number, number, number]; - events: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; - triggers: { uuid: string; type: string; isUsed: boolean }[] | []; - }[]; - pathPosition: [number, number, number]; - pathRotation: [number, number, number]; - speed: number; -} - -function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject }) { - const { renderDistance } = useRenderDistance(); - const { setSelectedEventSphere, selectedEventSphere } = useSelectedEventSphere(); - const { setSelectedPath } = useSelectedPath(); - const { simulationPaths, setSimulationPaths } = useSimulationPaths(); - const { isConnecting, setIsConnecting } = useIsConnecting(); - const { camera } = useThree(); - - const groupRefs = useRef<{ [key: string]: THREE.Group }>({}); - const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); - const transformRef = useRef(null); - const [transformMode, setTransformMode] = useState<'translate' | 'rotate' | null>(null); - - useEffect(() => { - setTransformMode(null); - const handleKeyDown = (e: KeyboardEvent) => { - if (!selectedEventSphere) return; - if (e.key === 'g') { - setTransformMode(prev => prev === 'translate' ? null : 'translate'); - } - if (e.key === 'r') { - setTransformMode(prev => prev === 'rotate' ? null : 'rotate'); - } - }; - - window.addEventListener('keydown', handleKeyDown); - return () => window.removeEventListener('keydown', handleKeyDown); - }, [selectedEventSphere]); - - useFrame(() => { - Object.values(groupRefs.current).forEach(group => { - if (group) { - const distance = new THREE.Vector3(...group.position.toArray()).distanceTo(camera.position); - group.visible = distance <= renderDistance; - } - }); - }); - - const updateSimulationPaths = () => { - if (!selectedEventSphere) return; - - const updatedPaths: Path[] = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedEventSphere.point.uuid - ? { - ...point, - position: [ - selectedEventSphere.point.position.x, - selectedEventSphere.point.position.y, - selectedEventSphere.point.position.z, - ], - rotation: [ - selectedEventSphere.point.rotation.x, - selectedEventSphere.point.rotation.y, - selectedEventSphere.point.rotation.z, - ] - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - - return ( - - {simulationPaths.map((path) => { - const points = path.points.map(point => new THREE.Vector3(...point.position)); - - return ( - (groupRefs.current[path.modeluuid] = el!)} - position={path.pathPosition} - rotation={path.pathRotation} - onClick={(e) => { - if (isConnecting) return; - e.stopPropagation(); - setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); - setSelectedEventSphere(null); - setTransformMode(null); - }} - onPointerMissed={() => { - setSelectedPath(null); - }} - > - {path.points.map((point, index) => ( - (sphereRefs.current[point.uuid] = el!)} - onClick={(e) => { - if (isConnecting) return; - e.stopPropagation(); - setSelectedEventSphere({ - path, - point: sphereRefs.current[point.uuid] - }); - setSelectedPath(null); - }} - userData={{ point, path }} - onPointerMissed={() => setSelectedEventSphere(null)} - > - - - ))} - - {points.slice(0, -1).map((point, index) => { - const nextPoint = points[index + 1]; - const segmentCurve = new THREE.CatmullRomCurve3([point, nextPoint]); - const tubeGeometry = new THREE.TubeGeometry(segmentCurve, 20, 0.1, 16, false); - - return ( - - - - ); - })} - - ); - })} - - {selectedEventSphere && transformMode && ( - - )} - - ); -} - -export default PathCreation; +import * as THREE from 'three'; +import { useRef, useState, useEffect } from 'react'; +import { Sphere, TransformControls } from '@react-three/drei'; +import { useIsConnecting, useRenderDistance, useSelectedActionSphere, useSelectedPath, useSimulationPaths } from '../../../store/store'; +import { useFrame, useThree } from '@react-three/fiber'; +import { useSubModuleStore } from '../../../store/useModuleStore'; + +interface Path { + modeluuid: string; + modelName: string; + points: { + uuid: string; + position: [number, number, number]; + rotation: [number, number, number]; + actions: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; + triggers: { uuid: string; type: string; isUsed: boolean }[] | []; + }[]; + pathPosition: [number, number, number]; + pathRotation: [number, number, number]; + speed: number; +} + +function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject }) { + const { renderDistance } = useRenderDistance(); + const { setSubModule } = useSubModuleStore(); + const { setSelectedActionSphere, selectedActionSphere } = useSelectedActionSphere(); + const { setSelectedPath } = useSelectedPath(); + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); + const { isConnecting, setIsConnecting } = useIsConnecting(); + const { camera } = useThree(); + + const groupRefs = useRef<{ [key: string]: THREE.Group }>({}); + const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); + const transformRef = useRef(null); + const [transformMode, setTransformMode] = useState<'translate' | 'rotate' | null>(null); + + useEffect(() => { + setTransformMode(null); + const handleKeyDown = (e: KeyboardEvent) => { + if (!selectedActionSphere) return; + if (e.key === 'g') { + setTransformMode(prev => prev === 'translate' ? null : 'translate'); + } + if (e.key === 'r') { + setTransformMode(prev => prev === 'rotate' ? null : 'rotate'); + } + }; + + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [selectedActionSphere]); + + useFrame(() => { + Object.values(groupRefs.current).forEach(group => { + if (group) { + const distance = new THREE.Vector3(...group.position.toArray()).distanceTo(camera.position); + group.visible = distance <= renderDistance; + } + }); + }); + + const updateSimulationPaths = () => { + if (!selectedActionSphere) return; + + const updatedPaths: Path[] = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + position: [ + selectedActionSphere.point.position.x, + selectedActionSphere.point.position.y, + selectedActionSphere.point.position.z, + ], + rotation: [ + selectedActionSphere.point.rotation.x, + selectedActionSphere.point.rotation.y, + selectedActionSphere.point.rotation.z, + ] + } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + + return ( + + {simulationPaths.map((path) => { + const points = path.points.map(point => new THREE.Vector3(...point.position)); + + return ( + (groupRefs.current[path.modeluuid] = el!)} + position={path.pathPosition} + rotation={path.pathRotation} + onClick={(e) => { + if (isConnecting) return; + e.stopPropagation(); + setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); + setSelectedActionSphere(null); + setTransformMode(null); + }} + onPointerMissed={() => { + setSelectedPath(null); + setSubModule('properties'); + }} + > + {path.points.map((point, index) => ( + (sphereRefs.current[point.uuid] = el!)} + onClick={(e) => { + if (isConnecting) return; + e.stopPropagation(); + setSelectedActionSphere({ + path, + point: sphereRefs.current[point.uuid] + }); + setSubModule('mechanics'); + setSelectedPath(null); + }} + userData={{ point, path }} + onPointerMissed={() => { + setSubModule('properties'); + setSelectedActionSphere(null) + }} + > + + + ))} + + {points.slice(0, -1).map((point, index) => { + const nextPoint = points[index + 1]; + const segmentCurve = new THREE.CatmullRomCurve3([point, nextPoint]); + const tubeGeometry = new THREE.TubeGeometry(segmentCurve, 20, 0.1, 16, false); + + return ( + + + + ); + })} + + ); + })} + + {selectedActionSphere && transformMode && ( + + )} + + ); +} + +export default PathCreation; diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx index 6851e9d..8bb389a 100644 --- a/app/src/modules/simulation/simulation.tsx +++ b/app/src/modules/simulation/simulation.tsx @@ -1,46 +1,46 @@ -import { useState, useEffect, useRef } from 'react'; -import { useConnections, useFloorItems, useSelectedEventSphere, useSelectedPath, useSimulationPaths } from '../../store/store'; -import { useThree } from '@react-three/fiber'; -import * as THREE from 'three'; -import Behaviour from './behaviour/behaviour'; -import PathCreation from './path/pathCreation'; -import PathConnector from './path/pathConnector'; -import useModuleStore from '../../store/useModuleStore'; - -function Simulation() { - const { activeModule } = useModuleStore(); - const pathsGroupRef = useRef() as React.MutableRefObject; - const { simulationPaths, setSimulationPaths } = useSimulationPaths(); - const { connections, setConnections, addConnection, removeConnection } = useConnections(); - const [processes, setProcesses] = useState([]); - - useEffect(() => { - console.log('simulationPaths: ', simulationPaths); - }, [simulationPaths]); - - // useEffect(() => { - // if (selectedEventSphere) { - // console.log('selectedEventSphere: ', selectedEventSphere); - // } - // }, [selectedEventSphere]); - - // useEffect(() => { - // if (selectedPath) { - // console.log('selectedPath: ', selectedPath); - // } - // }, [selectedPath]); - - return ( - <> - {activeModule === 'simulation' && ( - <> - - - - - )} - - ); -} - +import { useState, useEffect, useRef } from 'react'; +import { useConnections, useFloorItems, useSelectedActionSphere, useSelectedPath, useSimulationPaths } from '../../store/store'; +import { useThree } from '@react-three/fiber'; +import * as THREE from 'three'; +import Behaviour from './behaviour/behaviour'; +import PathCreation from './path/pathCreation'; +import PathConnector from './path/pathConnector'; +import useModuleStore from '../../store/useModuleStore'; + +function Simulation() { + const { activeModule } = useModuleStore(); + const pathsGroupRef = useRef() as React.MutableRefObject; + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); + const { connections, setConnections, addConnection, removeConnection } = useConnections(); + const [processes, setProcesses] = useState([]); + + useEffect(() => { + console.log('simulationPaths: ', simulationPaths); + }, [simulationPaths]); + + // useEffect(() => { + // if (selectedActionSphere) { + // console.log('selectedActionSphere: ', selectedActionSphere); + // } + // }, [selectedActionSphere]); + + // useEffect(() => { + // if (selectedPath) { + // console.log('selectedPath: ', selectedPath); + // } + // }, [selectedPath]); + + return ( + <> + {activeModule === 'simulation' && ( + <> + + + + + )} + + ); +} + export default Simulation; \ No newline at end of file diff --git a/app/src/modules/simulation/simulationUI.tsx b/app/src/modules/simulation/simulationUI.tsx new file mode 100644 index 0000000..1ce60e7 --- /dev/null +++ b/app/src/modules/simulation/simulationUI.tsx @@ -0,0 +1,381 @@ +import { useMemo, useState } from 'react'; +import { useSelectedActionSphere, useToggleView, useSimulationPaths, useSelectedPath, useStartSimulation } from '../../store/store'; +import * as THREE from 'three'; +import useModuleStore from '../../store/useModuleStore'; + +function SimulationUI() { + const { ToggleView } = useToggleView(); + const { activeModule } = useModuleStore(); + const { startSimulation, setStartSimulation } = useStartSimulation(); + const { selectedActionSphere } = useSelectedActionSphere(); + const { selectedPath, setSelectedPath } = useSelectedPath(); + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); + + const handleAddAction = () => { + if (!selectedActionSphere) return; + + const newAction = { uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, actions: [...point.actions, newAction] } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const handleDeleteAction = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const handleActionSelect = (uuid: string, actionType: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, type: actionType } : action + ), + } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const handleMaterialSelect = (uuid: string, material: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, material } : action + ), + } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const handleDelayChange = (uuid: string, delay: number | string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, delay } : action + ), + } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, spawnInterval } : action + ), + } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const handleSpeedChange = (speed: number) => { + if (!selectedPath) return; + + const updatedPaths = simulationPaths.map((path) => + path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path + ); + + setSimulationPaths(updatedPaths); + setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); + }; + + const handleAddTrigger = () => { + if (!selectedActionSphere) return; + + const newTrigger = { uuid: THREE.MathUtils.generateUUID(), type: '', isUsed: false }; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, triggers: [...point.triggers, newTrigger] } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const handleDeleteTrigger = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const handleTriggerSelect = (uuid: string, triggerType: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + triggers: point.triggers.map((trigger) => + trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger + ), + } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const handleResetPath = () => { + if (!selectedPath) return; + + }; + + + const handleActionToggle = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => ({ + ...action, + isUsed: action.uuid === uuid ? !action.isUsed : false, + })), + } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const handleTriggerToggle = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + triggers: point.triggers.map((trigger) => ({ + ...trigger, + isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, + })), + } + : point + ), + })); + + setSimulationPaths(updatedPaths); + }; + + const selectedPoint = useMemo(() => { + if (!selectedActionSphere) return null; + return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid); + }, [selectedActionSphere, simulationPaths]); + + return ( + <> + {activeModule === "simulation" && ( +
+ {!ToggleView && ( + <> + + + {selectedPath && ( +
+ + handleSpeedChange(parseFloat(e.target.value))} + /> +
+ )} + + {selectedActionSphere && ( +
+ + + + {selectedPoint?.actions.map((action) => ( +
+ + + + + {(action.type === 'Spawn' || action.type === 'Swap') && ( +
+ +
+ )} + + {action.type === 'Delay' && ( +
+ + handleDelayChange(action.uuid, parseInt(e.target.value) || 'Inherit')} + /> + +
+ )} + + {action.type === 'Spawn' && ( +
+ + handleSpawnIntervalChange(action.uuid, parseInt(e.target.value) || 'Inherit')} + /> + +
+ )} +
+
+ ))} + +
+ + {selectedPoint?.triggers.map((trigger) => ( +
+ + + +
+
+ ))} + + +
+ )} + + {selectedPath && ( +
+ +
+ )} + + )} +
+ )} + + ); +} + +export default SimulationUI; \ No newline at end of file diff --git a/app/src/modules/simulation/simulationtemp/collider/colliderCreator.tsx b/app/src/modules/simulation/simulationtemp/collider/colliderCreator.tsx index 3f3a487..ec5e14b 100644 --- a/app/src/modules/simulation/simulationtemp/collider/colliderCreator.tsx +++ b/app/src/modules/simulation/simulationtemp/collider/colliderCreator.tsx @@ -1,9 +1,9 @@ -import React from 'react' - -function ColliderCreator() { - return ( - <> - ) -} - +import React from 'react' + +function ColliderCreator() { + return ( + <> + ) +} + export default ColliderCreator \ No newline at end of file diff --git a/app/src/modules/simulation/simulationtemp/path/pathCreator.tsx b/app/src/modules/simulation/simulationtemp/path/pathCreator.tsx index f77894b..1c63289 100644 --- a/app/src/modules/simulation/simulationtemp/path/pathCreator.tsx +++ b/app/src/modules/simulation/simulationtemp/path/pathCreator.tsx @@ -1,404 +1,404 @@ -import { useEffect, useState } from 'react'; -import * as THREE from 'three'; -import { useThree, useFrame } from '@react-three/fiber'; -import { Line, TransformControls } from '@react-three/drei'; -import { useDrawMaterialPath } from '../../../../store/store'; - -type PathPoint = { - position: THREE.Vector3; - rotation: THREE.Quaternion; - uuid: string; -}; - -type PathCreatorProps = { - simulationPaths: PathPoint[][]; - setSimulationPaths: React.Dispatch>; - connections: { start: PathPoint; end: PathPoint }[]; - setConnections: React.Dispatch> -}; - -const PathCreator = ({ simulationPaths, setSimulationPaths, connections, setConnections }: PathCreatorProps) => { - const { camera, scene, raycaster, pointer, gl } = useThree(); - const { drawMaterialPath } = useDrawMaterialPath(); - - const [currentPath, setCurrentPath] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }[]>([]); - const [temporaryPoint, setTemporaryPoint] = useState(null); - const [selectedPoint, setSelectedPoint] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string } | null>(null); - const [selectedConnectionPoint, setSelectedConnectionPoint] = useState<{ point: PathPoint; pathIndex: number } | null>(null); - const [previewConnection, setPreviewConnection] = useState<{ start: PathPoint; end?: THREE.Vector3 } | null>(null); - const [transformMode, setTransformMode] = useState<'translate' | 'rotate'>('translate'); - - useEffect(() => { - const handleKeyDown = (event: KeyboardEvent) => { - if (selectedPoint) { - if (event.key === 'g') { - setTransformMode('translate'); - } else if (event.key === 'r') { - setTransformMode('rotate'); - } - } - }; - - document.addEventListener('keydown', handleKeyDown); - - return () => { - document.removeEventListener('keydown', handleKeyDown); - }; - }, [selectedPoint]); - - useEffect(() => { - const canvasElement = gl.domElement; - - let drag = false; - let MouseDown = false; - - const onMouseDown = () => { - MouseDown = true; - drag = false; - }; - - const onMouseUp = () => { - MouseDown = false; - }; - - const onMouseMove = () => { - if (MouseDown) { - drag = true; - } - }; - - const onContextMenu = (e: any) => { - e.preventDefault(); - if (drag || e.button === 0) return; - if (currentPath.length > 1) { - setSimulationPaths((prevPaths) => [...prevPaths, currentPath]); - } - setCurrentPath([]); - setTemporaryPoint(null); - setPreviewConnection(null); - setSelectedConnectionPoint(null); - }; - - const onMouseClick = (evt: any) => { - if (drag || evt.button !== 0) return; - - evt.preventDefault(); - raycaster.setFromCamera(pointer, camera); - - let intersects = raycaster.intersectObjects(scene.children, true); - - if (intersects.some((intersect) => intersect.object.name.includes("path-point"))) { - intersects = []; - } else { - intersects = intersects.filter( - (intersect) => - !intersect.object.name.includes("Roof") && - !intersect.object.name.includes("MeasurementReference") && - !intersect.object.userData.isPathObject && - !(intersect.object.type === "GridHelper") - ); - } - - if (intersects.length > 0 && selectedPoint === null) { - let point = intersects[0].point; - if (point.y < 0.05) { - point = new THREE.Vector3(point.x, 0.05, point.z); - } - const newPoint = { - position: point, - rotation: new THREE.Quaternion(), - uuid: THREE.MathUtils.generateUUID(), - }; - setCurrentPath((prevPath) => [...prevPath, newPoint]); - setTemporaryPoint(null); - } else { - setSelectedPoint(null); - } - }; - - if (drawMaterialPath) { - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - canvasElement.addEventListener("click", onMouseClick); - canvasElement.addEventListener("contextmenu", onContextMenu); - } else { - if (currentPath.length > 1) { - setSimulationPaths((prevPaths) => [...prevPaths, currentPath]); - } - setCurrentPath([]); - setTemporaryPoint(null); - } - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - canvasElement.removeEventListener("click", onMouseClick); - canvasElement.removeEventListener("contextmenu", onContextMenu); - }; - }, [camera, scene, raycaster, currentPath, drawMaterialPath, selectedPoint]); - - useFrame(() => { - if (drawMaterialPath && currentPath.length > 0) { - raycaster.setFromCamera(pointer, camera); - - const intersects = raycaster.intersectObjects(scene.children, true).filter( - (intersect) => - !intersect.object.name.includes("Roof") && - !intersect.object.name.includes("MeasurementReference") && - !intersect.object.userData.isPathObject && - !(intersect.object.type === "GridHelper") - ); - - if (intersects.length > 0) { - let point = intersects[0].point; - if (point.y < 0.05) { - point = new THREE.Vector3(point.x, 0.05, point.z); - } - setTemporaryPoint(point); - } else { - setTemporaryPoint(null); - } - } else { - setTemporaryPoint(null); - } - }); - - const handlePointClick = (point: { position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }) => { - if (currentPath.length === 0 && drawMaterialPath) { - setSelectedPoint(point); - } else { - setSelectedPoint(null); - } - }; - - const handleTransform = (e: any) => { - if (selectedPoint) { - const updatedPosition = e.target.object.position.clone(); - const updatedRotation = e.target.object.quaternion.clone(); - const updatedPaths = simulationPaths.map((path) => - path.map((p) => - p.uuid === selectedPoint.uuid ? { ...p, position: updatedPosition, rotation: updatedRotation } : p - ) - ); - setSimulationPaths(updatedPaths); - } - }; - - - const meshContext = (uuid: string) => { - const pathIndex = simulationPaths.findIndex(path => path.some(point => point.uuid === uuid)); - if (pathIndex === -1) return; - - const clickedPoint = simulationPaths[pathIndex].find(point => point.uuid === uuid); - if (!clickedPoint) return; - - const isStart = simulationPaths[pathIndex][0].uuid === uuid; - const isEnd = simulationPaths[pathIndex][simulationPaths[pathIndex].length - 1].uuid === uuid; - - if (pathIndex === 0 && isStart) { - console.log("The first-ever point is not connectable."); - setSelectedConnectionPoint(null); - setPreviewConnection(null); - return; - } - - if (!isStart && !isEnd) { - console.log("Selected point is not a valid connection point (not start or end)"); - setSelectedConnectionPoint(null); - setPreviewConnection(null); - return; - } - - if (connections.some(conn => conn.start.uuid === uuid || conn.end.uuid === uuid)) { - console.log("The selected point is already connected."); - setSelectedConnectionPoint(null); - setPreviewConnection(null); - return; - } - - if (!selectedConnectionPoint) { - setSelectedConnectionPoint({ point: clickedPoint, pathIndex }); - setPreviewConnection({ start: clickedPoint }); - console.log("First point selected for connection:", clickedPoint); - return; - } - - if (selectedConnectionPoint.pathIndex === pathIndex) { - console.log("Cannot connect points within the same path."); - setSelectedConnectionPoint(null); - setPreviewConnection(null); - return; - } - - if (connections.some(conn => conn.start.uuid === clickedPoint.uuid || conn.end.uuid === clickedPoint.uuid)) { - console.log("The target point is already connected."); - setSelectedConnectionPoint(null); - setPreviewConnection(null); - return; - } - - setConnections(prevConnections => [ - ...prevConnections, - { start: selectedConnectionPoint.point, end: clickedPoint }, - ]); - - - setSelectedConnectionPoint(null); - setPreviewConnection(null); - }; - - useEffect(() => { - if (!selectedConnectionPoint) { - setPreviewConnection(null); - } - }, [selectedConnectionPoint, connections]); - - useFrame(() => { - if (selectedConnectionPoint) { - raycaster.setFromCamera(pointer, camera); - - const intersects = raycaster.intersectObjects(scene.children, true).filter( - (intersect) => - !intersect.object.name.includes("Roof") && - !intersect.object.name.includes("MeasurementReference") && - !intersect.object.userData.isPathObject && - !(intersect.object.type === "GridHelper") - ); - - if (intersects.length > 0) { - let point = intersects[0].point; - if (point.y < 0.05) { - point = new THREE.Vector3(point.x, 0.05, point.z); - } - setPreviewConnection({ start: selectedConnectionPoint.point, end: point }); - } else { - setPreviewConnection(null); - } - } - }); - - return ( - <> - - {/* Render finalized simulationPaths */} - {simulationPaths.map((path, pathIndex) => ( - - point.position)} - color="yellow" - lineWidth={5} - userData={{ isPathObject: true }} - /> - - ))} - - {/* Render finalized points */} - {simulationPaths.map((path) => - path.map((point) => ( - handlePointClick(point)} - onPointerMissed={() => { setSelectedPoint(null) }} - onContextMenu={() => { meshContext(point.uuid); }} - > - - - - )) - )} - - {connections.map((conn, index) => ( - - ))} - - - - {/* Render current path */} - {currentPath.length > 1 && ( - - point.position)} - color="red" - lineWidth={5} - userData={{ isPathObject: true }} - /> - - )} - - {/* Render current path points */} - {currentPath.map((point) => ( - - - - - ))} - - {/* Render temporary indicator line */} - {temporaryPoint && currentPath.length > 0 && ( - - - - )} - - {/* Render dashed preview connection */} - {previewConnection && previewConnection.end && ( - - )} - - {/* Render temporary point */} - {temporaryPoint && ( - - - - - )} - - {/* Attach TransformControls to the selected point */} - {selectedPoint && ( - - )} - - ); -}; - +import { useEffect, useState } from 'react'; +import * as THREE from 'three'; +import { useThree, useFrame } from '@react-three/fiber'; +import { Line, TransformControls } from '@react-three/drei'; +import { useDrawMaterialPath } from '../../../../store/store'; + +type PathPoint = { + position: THREE.Vector3; + rotation: THREE.Quaternion; + uuid: string; +}; + +type PathCreatorProps = { + simulationPaths: PathPoint[][]; + setSimulationPaths: React.Dispatch>; + connections: { start: PathPoint; end: PathPoint }[]; + setConnections: React.Dispatch> +}; + +const PathCreator = ({ simulationPaths, setSimulationPaths, connections, setConnections }: PathCreatorProps) => { + const { camera, scene, raycaster, pointer, gl } = useThree(); + const { drawMaterialPath } = useDrawMaterialPath(); + + const [currentPath, setCurrentPath] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }[]>([]); + const [temporaryPoint, setTemporaryPoint] = useState(null); + const [selectedPoint, setSelectedPoint] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string } | null>(null); + const [selectedConnectionPoint, setSelectedConnectionPoint] = useState<{ point: PathPoint; pathIndex: number } | null>(null); + const [previewConnection, setPreviewConnection] = useState<{ start: PathPoint; end?: THREE.Vector3 } | null>(null); + const [transformMode, setTransformMode] = useState<'translate' | 'rotate'>('translate'); + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (selectedPoint) { + if (event.key === 'g') { + setTransformMode('translate'); + } else if (event.key === 'r') { + setTransformMode('rotate'); + } + } + }; + + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [selectedPoint]); + + useEffect(() => { + const canvasElement = gl.domElement; + + let drag = false; + let MouseDown = false; + + const onMouseDown = () => { + MouseDown = true; + drag = false; + }; + + const onMouseUp = () => { + MouseDown = false; + }; + + const onMouseMove = () => { + if (MouseDown) { + drag = true; + } + }; + + const onContextMenu = (e: any) => { + e.preventDefault(); + if (drag || e.button === 0) return; + if (currentPath.length > 1) { + setSimulationPaths((prevPaths) => [...prevPaths, currentPath]); + } + setCurrentPath([]); + setTemporaryPoint(null); + setPreviewConnection(null); + setSelectedConnectionPoint(null); + }; + + const onMouseClick = (evt: any) => { + if (drag || evt.button !== 0) return; + + evt.preventDefault(); + raycaster.setFromCamera(pointer, camera); + + let intersects = raycaster.intersectObjects(scene.children, true); + + if (intersects.some((intersect) => intersect.object.name.includes("path-point"))) { + intersects = []; + } else { + intersects = intersects.filter( + (intersect) => + !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("MeasurementReference") && + !intersect.object.userData.isPathObject && + !(intersect.object.type === "GridHelper") + ); + } + + if (intersects.length > 0 && selectedPoint === null) { + let point = intersects[0].point; + if (point.y < 0.05) { + point = new THREE.Vector3(point.x, 0.05, point.z); + } + const newPoint = { + position: point, + rotation: new THREE.Quaternion(), + uuid: THREE.MathUtils.generateUUID(), + }; + setCurrentPath((prevPath) => [...prevPath, newPoint]); + setTemporaryPoint(null); + } else { + setSelectedPoint(null); + } + }; + + if (drawMaterialPath) { + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + canvasElement.addEventListener("click", onMouseClick); + canvasElement.addEventListener("contextmenu", onContextMenu); + } else { + if (currentPath.length > 1) { + setSimulationPaths((prevPaths) => [...prevPaths, currentPath]); + } + setCurrentPath([]); + setTemporaryPoint(null); + } + + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + canvasElement.removeEventListener("click", onMouseClick); + canvasElement.removeEventListener("contextmenu", onContextMenu); + }; + }, [camera, scene, raycaster, currentPath, drawMaterialPath, selectedPoint]); + + useFrame(() => { + if (drawMaterialPath && currentPath.length > 0) { + raycaster.setFromCamera(pointer, camera); + + const intersects = raycaster.intersectObjects(scene.children, true).filter( + (intersect) => + !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("MeasurementReference") && + !intersect.object.userData.isPathObject && + !(intersect.object.type === "GridHelper") + ); + + if (intersects.length > 0) { + let point = intersects[0].point; + if (point.y < 0.05) { + point = new THREE.Vector3(point.x, 0.05, point.z); + } + setTemporaryPoint(point); + } else { + setTemporaryPoint(null); + } + } else { + setTemporaryPoint(null); + } + }); + + const handlePointClick = (point: { position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }) => { + if (currentPath.length === 0 && drawMaterialPath) { + setSelectedPoint(point); + } else { + setSelectedPoint(null); + } + }; + + const handleTransform = (e: any) => { + if (selectedPoint) { + const updatedPosition = e.target.object.position.clone(); + const updatedRotation = e.target.object.quaternion.clone(); + const updatedPaths = simulationPaths.map((path) => + path.map((p) => + p.uuid === selectedPoint.uuid ? { ...p, position: updatedPosition, rotation: updatedRotation } : p + ) + ); + setSimulationPaths(updatedPaths); + } + }; + + + const meshContext = (uuid: string) => { + const pathIndex = simulationPaths.findIndex(path => path.some(point => point.uuid === uuid)); + if (pathIndex === -1) return; + + const clickedPoint = simulationPaths[pathIndex].find(point => point.uuid === uuid); + if (!clickedPoint) return; + + const isStart = simulationPaths[pathIndex][0].uuid === uuid; + const isEnd = simulationPaths[pathIndex][simulationPaths[pathIndex].length - 1].uuid === uuid; + + if (pathIndex === 0 && isStart) { + console.log("The first-ever point is not connectable."); + setSelectedConnectionPoint(null); + setPreviewConnection(null); + return; + } + + if (!isStart && !isEnd) { + console.log("Selected point is not a valid connection point (not start or end)"); + setSelectedConnectionPoint(null); + setPreviewConnection(null); + return; + } + + if (connections.some(conn => conn.start.uuid === uuid || conn.end.uuid === uuid)) { + console.log("The selected point is already connected."); + setSelectedConnectionPoint(null); + setPreviewConnection(null); + return; + } + + if (!selectedConnectionPoint) { + setSelectedConnectionPoint({ point: clickedPoint, pathIndex }); + setPreviewConnection({ start: clickedPoint }); + console.log("First point selected for connection:", clickedPoint); + return; + } + + if (selectedConnectionPoint.pathIndex === pathIndex) { + console.log("Cannot connect points within the same path."); + setSelectedConnectionPoint(null); + setPreviewConnection(null); + return; + } + + if (connections.some(conn => conn.start.uuid === clickedPoint.uuid || conn.end.uuid === clickedPoint.uuid)) { + console.log("The target point is already connected."); + setSelectedConnectionPoint(null); + setPreviewConnection(null); + return; + } + + setConnections(prevConnections => [ + ...prevConnections, + { start: selectedConnectionPoint.point, end: clickedPoint }, + ]); + + + setSelectedConnectionPoint(null); + setPreviewConnection(null); + }; + + useEffect(() => { + if (!selectedConnectionPoint) { + setPreviewConnection(null); + } + }, [selectedConnectionPoint, connections]); + + useFrame(() => { + if (selectedConnectionPoint) { + raycaster.setFromCamera(pointer, camera); + + const intersects = raycaster.intersectObjects(scene.children, true).filter( + (intersect) => + !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("MeasurementReference") && + !intersect.object.userData.isPathObject && + !(intersect.object.type === "GridHelper") + ); + + if (intersects.length > 0) { + let point = intersects[0].point; + if (point.y < 0.05) { + point = new THREE.Vector3(point.x, 0.05, point.z); + } + setPreviewConnection({ start: selectedConnectionPoint.point, end: point }); + } else { + setPreviewConnection(null); + } + } + }); + + return ( + <> + + {/* Render finalized simulationPaths */} + {simulationPaths.map((path, pathIndex) => ( + + point.position)} + color="yellow" + lineWidth={5} + userData={{ isPathObject: true }} + /> + + ))} + + {/* Render finalized points */} + {simulationPaths.map((path) => + path.map((point) => ( + handlePointClick(point)} + onPointerMissed={() => { setSelectedPoint(null) }} + onContextMenu={() => { meshContext(point.uuid); }} + > + + + + )) + )} + + {connections.map((conn, index) => ( + + ))} + + + + {/* Render current path */} + {currentPath.length > 1 && ( + + point.position)} + color="red" + lineWidth={5} + userData={{ isPathObject: true }} + /> + + )} + + {/* Render current path points */} + {currentPath.map((point) => ( + + + + + ))} + + {/* Render temporary indicator line */} + {temporaryPoint && currentPath.length > 0 && ( + + + + )} + + {/* Render dashed preview connection */} + {previewConnection && previewConnection.end && ( + + )} + + {/* Render temporary point */} + {temporaryPoint && ( + + + + + )} + + {/* Attach TransformControls to the selected point */} + {selectedPoint && ( + + )} + + ); +}; + export default PathCreator; \ No newline at end of file diff --git a/app/src/modules/simulation/simulationtemp/path/pathFlow.tsx b/app/src/modules/simulation/simulationtemp/path/pathFlow.tsx index 1ec8ba8..63d38e2 100644 --- a/app/src/modules/simulation/simulationtemp/path/pathFlow.tsx +++ b/app/src/modules/simulation/simulationtemp/path/pathFlow.tsx @@ -1,164 +1,164 @@ -import * as THREE from 'three'; -import { useState, useEffect, useRef, useMemo } from "react"; -import { useLoader, useFrame } from "@react-three/fiber"; -import { GLTFLoader } from "three-stdlib"; -import crate from "../../../../assets/models/gltf-glb/crate_box.glb"; -import { useOrganization } from '../../../../store/store'; -import { useControls } from 'leva'; - -type PathPoint = { - position: THREE.Vector3; - rotation: THREE.Quaternion; - uuid: string; -}; - -type PathFlowProps = { - path: PathPoint[]; - connections: { start: PathPoint; end: PathPoint }[]; -}; - -export default function PathFlow({ path, connections }: PathFlowProps) { - const { organization } = useOrganization(); - const [isPaused, setIsPaused] = useState(false); - const [isStopped, setIsStopped] = useState(false); - - const { spawnInterval, speed, pauseResume, startStop } = useControls({ - spawnInterval: { value: 1000, min: 500, max: 5000, step: 100 }, - speed: { value: 2, min: 1, max: 20, step: 0.5 }, - pauseResume: { value: false, label: "Pause/Resume" }, - startStop: { value: false, label: "Start/Stop" }, - }); - - const [meshes, setMeshes] = useState<{ id: number }[]>([]); - const gltf = useLoader(GLTFLoader, crate); - - const meshIdRef = useRef(0); - const lastSpawnTime = useRef(performance.now()); - const totalPausedTime = useRef(0); - const pauseStartTime = useRef(null); - - useEffect(() => { - setIsPaused(pauseResume); - setIsStopped(startStop); - }, [pauseResume, startStop]); - - const removeMesh = (id: number) => { - setMeshes((prev) => prev.filter((m) => m.id !== id)); - }; - - useFrame(() => { - if (organization !== 'hexrfactory' || isStopped || !path) return; - - const now = performance.now(); - - if (isPaused) { - if (pauseStartTime.current === null) { - pauseStartTime.current = now; - } - return; - } - - if (pauseStartTime.current !== null) { - totalPausedTime.current += now - pauseStartTime.current; - pauseStartTime.current = null; - } - - const adjustedTime = now - totalPausedTime.current; - - if (adjustedTime - lastSpawnTime.current >= spawnInterval) { - setMeshes((prev) => [...prev, { id: meshIdRef.current++ }]); - lastSpawnTime.current = adjustedTime; - } - }); - - return ( - <> - {meshes.map((mesh) => ( - - ))} - - ); -} - -function MovingMesh({ meshId, points, speed, gltf, removeMesh, isPaused }: any) { - const meshRef = useRef(); - const startTime = useRef(null); // Initialize as null - const pausedTime = useRef(0); - const pauseStartTime = useRef(null); - - const distances = useMemo(() => { - if (!points || points.length < 2) return []; - return points.slice(1).map((point: any, i: number) => points[i].position.distanceTo(point.position)); - }, [points]); - - useFrame(() => { - if (!points || points.length < 2) return; - - if (startTime.current === null && points.length > 0) { - startTime.current = performance.now(); - } - - if (!meshRef.current) return; - - if (isPaused) { - if (pauseStartTime.current === null) { - pauseStartTime.current = performance.now(); - } - return; - } - - if (pauseStartTime.current !== null) { - pausedTime.current += performance.now() - pauseStartTime.current; - pauseStartTime.current = null; - } - - if (startTime.current === null) return; - - const elapsed = performance.now() - startTime.current - pausedTime.current; - - const distanceTraveled = elapsed / 1000 * speed; - - let remainingDistance = distanceTraveled; - let currentSegmentIndex = 0; - - while (currentSegmentIndex < distances.length && remainingDistance > distances[currentSegmentIndex]) { - remainingDistance -= distances[currentSegmentIndex]; - currentSegmentIndex++; - } - - if (currentSegmentIndex >= distances.length) { - removeMesh(meshId); - return; - } - - const progress = remainingDistance / distances[currentSegmentIndex]; - const start = points[currentSegmentIndex].position; - const end = points[currentSegmentIndex + 1].position; - - meshRef.current.position.lerpVectors(start, end, Math.min(progress, 1)); - - const startRotation = points[currentSegmentIndex].rotation; - const endRotation = points[currentSegmentIndex + 1].rotation; - const interpolatedRotation = new THREE.Quaternion().slerpQuaternions(startRotation, endRotation, Math.min(progress, 1)); - - meshRef.current.quaternion.copy(interpolatedRotation); - }); - - return ( - <> - {points && points.length > 0 && - - - - } - - ); +import * as THREE from 'three'; +import { useState, useEffect, useRef, useMemo } from "react"; +import { useLoader, useFrame } from "@react-three/fiber"; +import { GLTFLoader } from "three-stdlib"; +import crate from "../../../../assets/models/gltf-glb/crate_box.glb"; +import { useOrganization } from '../../../../store/store'; +import { useControls } from 'leva'; + +type PathPoint = { + position: THREE.Vector3; + rotation: THREE.Quaternion; + uuid: string; +}; + +type PathFlowProps = { + path: PathPoint[]; + connections: { start: PathPoint; end: PathPoint }[]; +}; + +export default function PathFlow({ path, connections }: PathFlowProps) { + const { organization } = useOrganization(); + const [isPaused, setIsPaused] = useState(false); + const [isStopped, setIsStopped] = useState(false); + + const { spawnInterval, speed, pauseResume, startStop } = useControls({ + spawnInterval: { value: 1000, min: 500, max: 5000, step: 100 }, + speed: { value: 2, min: 1, max: 20, step: 0.5 }, + pauseResume: { value: false, label: "Pause/Resume" }, + startStop: { value: false, label: "Start/Stop" }, + }); + + const [meshes, setMeshes] = useState<{ id: number }[]>([]); + const gltf = useLoader(GLTFLoader, crate); + + const meshIdRef = useRef(0); + const lastSpawnTime = useRef(performance.now()); + const totalPausedTime = useRef(0); + const pauseStartTime = useRef(null); + + useEffect(() => { + setIsPaused(pauseResume); + setIsStopped(startStop); + }, [pauseResume, startStop]); + + const removeMesh = (id: number) => { + setMeshes((prev) => prev.filter((m) => m.id !== id)); + }; + + useFrame(() => { + if (organization !== 'hexrfactory' || isStopped || !path) return; + + const now = performance.now(); + + if (isPaused) { + if (pauseStartTime.current === null) { + pauseStartTime.current = now; + } + return; + } + + if (pauseStartTime.current !== null) { + totalPausedTime.current += now - pauseStartTime.current; + pauseStartTime.current = null; + } + + const adjustedTime = now - totalPausedTime.current; + + if (adjustedTime - lastSpawnTime.current >= spawnInterval) { + setMeshes((prev) => [...prev, { id: meshIdRef.current++ }]); + lastSpawnTime.current = adjustedTime; + } + }); + + return ( + <> + {meshes.map((mesh) => ( + + ))} + + ); +} + +function MovingMesh({ meshId, points, speed, gltf, removeMesh, isPaused }: any) { + const meshRef = useRef(); + const startTime = useRef(null); // Initialize as null + const pausedTime = useRef(0); + const pauseStartTime = useRef(null); + + const distances = useMemo(() => { + if (!points || points.length < 2) return []; + return points.slice(1).map((point: any, i: number) => points[i].position.distanceTo(point.position)); + }, [points]); + + useFrame(() => { + if (!points || points.length < 2) return; + + if (startTime.current === null && points.length > 0) { + startTime.current = performance.now(); + } + + if (!meshRef.current) return; + + if (isPaused) { + if (pauseStartTime.current === null) { + pauseStartTime.current = performance.now(); + } + return; + } + + if (pauseStartTime.current !== null) { + pausedTime.current += performance.now() - pauseStartTime.current; + pauseStartTime.current = null; + } + + if (startTime.current === null) return; + + const elapsed = performance.now() - startTime.current - pausedTime.current; + + const distanceTraveled = elapsed / 1000 * speed; + + let remainingDistance = distanceTraveled; + let currentSegmentIndex = 0; + + while (currentSegmentIndex < distances.length && remainingDistance > distances[currentSegmentIndex]) { + remainingDistance -= distances[currentSegmentIndex]; + currentSegmentIndex++; + } + + if (currentSegmentIndex >= distances.length) { + removeMesh(meshId); + return; + } + + const progress = remainingDistance / distances[currentSegmentIndex]; + const start = points[currentSegmentIndex].position; + const end = points[currentSegmentIndex + 1].position; + + meshRef.current.position.lerpVectors(start, end, Math.min(progress, 1)); + + const startRotation = points[currentSegmentIndex].rotation; + const endRotation = points[currentSegmentIndex + 1].rotation; + const interpolatedRotation = new THREE.Quaternion().slerpQuaternions(startRotation, endRotation, Math.min(progress, 1)); + + meshRef.current.quaternion.copy(interpolatedRotation); + }); + + return ( + <> + {points && points.length > 0 && + + + + } + + ); } \ No newline at end of file diff --git a/app/src/modules/simulation/simulationtemp/process/processCreator.tsx b/app/src/modules/simulation/simulationtemp/process/processCreator.tsx index 52ac683..1c5241d 100644 --- a/app/src/modules/simulation/simulationtemp/process/processCreator.tsx +++ b/app/src/modules/simulation/simulationtemp/process/processCreator.tsx @@ -1,9 +1,9 @@ -import React from 'react' - -function ProcessCreator() { - return ( - <> - ) -} - +import React from 'react' + +function ProcessCreator() { + return ( + <> + ) +} + export default ProcessCreator \ No newline at end of file diff --git a/app/src/modules/simulation/simulationtemp/simulation.tsx b/app/src/modules/simulation/simulationtemp/simulation.tsx index 828fa03..6224177 100644 --- a/app/src/modules/simulation/simulationtemp/simulation.tsx +++ b/app/src/modules/simulation/simulationtemp/simulation.tsx @@ -1,26 +1,26 @@ -import React, { useState } from 'react'; -import * as THREE from 'three'; -import PathCreator from './path/pathCreator'; -import PathFlow from './path/pathFlow'; - -type PathPoint = { - position: THREE.Vector3; - rotation: THREE.Quaternion; - uuid: string; -}; - -function Simulation() { - const [simulationPaths, setSimulationPaths] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }[][]>([]); - const [connections, setConnections] = useState<{ start: PathPoint; end: PathPoint }[]>([]); - - return ( - <> - - {simulationPaths.map((path, index) => ( - - ))} - - ); -} - +import React, { useState } from 'react'; +import * as THREE from 'three'; +import PathCreator from './path/pathCreator'; +import PathFlow from './path/pathFlow'; + +type PathPoint = { + position: THREE.Vector3; + rotation: THREE.Quaternion; + uuid: string; +}; + +function Simulation() { + const [simulationPaths, setSimulationPaths] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }[][]>([]); + const [connections, setConnections] = useState<{ start: PathPoint; end: PathPoint }[]>([]); + + return ( + <> + + {simulationPaths.map((path, index) => ( + + ))} + + ); +} + export default Simulation; \ No newline at end of file diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx index 64c8fb5..6be56a0 100644 --- a/app/src/pages/Project.tsx +++ b/app/src/pages/Project.tsx @@ -16,6 +16,7 @@ import { } from "../store/store"; import { useNavigate } from "react-router-dom"; import { usePlayButtonStore } from "../store/usePlayButtonStore"; +import SimulationUI from "../modules/simulation/simulationUI"; const Project: React.FC = () => { let navigate = useNavigate(); @@ -53,10 +54,17 @@ const Project: React.FC = () => { {!isPlaying && } {!isPlaying && } {activeModule === "visualization" && } - {activeModule !== "visualization" && } + {/* {activeModule !== "visualization" && } */} {/* */} + {/* */} +
+ {activeModule !== "visualization" && } +
); }; diff --git a/app/src/pages/UserAuth.tsx b/app/src/pages/UserAuth.tsx index 5b3f16c..b89f34e 100644 --- a/app/src/pages/UserAuth.tsx +++ b/app/src/pages/UserAuth.tsx @@ -2,6 +2,9 @@ import React, { useState, FormEvent } from "react"; import { useNavigate } from "react-router-dom"; import { LogoIconLarge } from "../components/icons/Logo"; import { EyeIcon } from "../components/icons/ExportCommonIcons"; +import { useOrganization, useUserName } from "../store/store"; +import { signInApi } from "../services/factoryBuilder/signInSignUp/signInApi"; +import { signUpApi } from "../services/factoryBuilder/signInSignUp/signUpApi"; // import LoadingPage from "../components/templates/LoadingPage"; const UserAuth: React.FC = () => { @@ -9,34 +12,50 @@ const UserAuth: React.FC = () => { const [password, setPassword] = useState(""); const [showPassword, setShowPassword] = useState(false); const [error, setError] = useState(""); - const [isSignIn, setIsSignIn] = useState(true); // Toggle between login and register - const [userName, setUserName] = useState(""); // Username for registration + const [isSignIn, setIsSignIn] = useState(true); + const { userName, setUserName } = useUserName(); + const { organization, setOrganization } = useOrganization(); const navigate = useNavigate(); - const handleLogin = (e: FormEvent) => { + const handleLogin = async (e: FormEvent) => { e.preventDefault(); - // Dummy validation for "account not found" - if (email !== "user@example.com") { - setError("Account not found"); - } else { - setError(""); - console.log("Login Successful!"); - console.log("Email:", email); - console.log("Password:", password); - } + + const organization = (email.split("@")[1]).split(".")[0]; + try { + const res = await signInApi(email, password, organization); + + if (res.message === "login successfull") { + setError(""); + setOrganization(organization); + setUserName(res.name); + localStorage.setItem("userId", res.userId); + localStorage.setItem("email", res.email); + localStorage.setItem("userName", res.name); + if (res.isShare) { + navigate("/Project"); + } + } else if (res.message === "User Not Found!!! Kindly signup...") { + setError("Account not found"); + } + } catch (error) { } }; - const handleRegister = (e: FormEvent) => { + const handleRegister = async (e: FormEvent) => { e.preventDefault(); - // Dummy validation for registration if (email && password && userName) { setError(""); - console.log("Registration Successful!"); - console.log("Username:", userName); - console.log("Email:", email); - console.log("Password:", password); - setIsSignIn(true); + try { + const organization = (email.split("@")[1]).split(".")[0]; + const res = await signUpApi(userName, email, password, organization); + + if (res.message === "New User created") { + setIsSignIn(true); + } + if (res.message === "User already exists") { + setError("User already exists"); + } + } catch (error) { } } else { setError("Please fill all the fields!"); } @@ -97,6 +116,7 @@ const UserAuth: React.FC = () => { )} setEmail(e.target.value)} @@ -104,6 +124,7 @@ const UserAuth: React.FC = () => { />
{ - if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); - } -}; - -export default reportWebVitals; +import { ReportHandler } from 'web-vitals'; + +const reportWebVitals = (onPerfEntry?: ReportHandler) => { + if (onPerfEntry && onPerfEntry instanceof Function) { + import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + getCLS(onPerfEntry); + getFID(onPerfEntry); + getFCP(onPerfEntry); + getLCP(onPerfEntry); + getTTFB(onPerfEntry); + }); + } +}; + +export default reportWebVitals; diff --git a/app/src/services/factoryBuilder/assest/assets/getAssetImages.ts b/app/src/services/factoryBuilder/assest/assets/getAssetImages.ts index 9d41601..72f09d1 100644 --- a/app/src/services/factoryBuilder/assest/assets/getAssetImages.ts +++ b/app/src/services/factoryBuilder/assest/assets/getAssetImages.ts @@ -1,23 +1,23 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; - -export const getAssetImages = async (cursor?: string) => { - try { - const response = await fetch( - `${url_Backend_dwinzo}/api/v3/AssetDatas?limit=10${cursor ? `&cursor=${cursor}` : ""}`, - { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - } - ); - - if (!response.ok) { - throw new Error("Failed to fetch assets"); - } - - return await response.json(); - } catch (error: any) { - throw new Error(error.message); - } -}; +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; + +export const getAssetImages = async (cursor?: string) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v3/AssetDatas?limit=10${cursor ? `&cursor=${cursor}` : ""}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + throw new Error("Failed to fetch assets"); + } + + return await response.json(); + } catch (error: any) { + throw new Error(error.message); + } +}; diff --git a/app/src/services/factoryBuilder/assest/assets/getAssetModel.ts b/app/src/services/factoryBuilder/assest/assets/getAssetModel.ts index cf1ed5a..4ccb6e9 100644 --- a/app/src/services/factoryBuilder/assest/assets/getAssetModel.ts +++ b/app/src/services/factoryBuilder/assest/assets/getAssetModel.ts @@ -1,25 +1,25 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; - -export const getAssetModel = async (modelId: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/AssetFile/${modelId}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); - - if (!response.ok) { - throw new Error("Failed to fetch model"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; + +export const getAssetModel = async (modelId: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/AssetFile/${modelId}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error("Failed to fetch model"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts index ecd7a54..fbbb042 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const deleteFloorItem = async (organization: string, modeluuid: string, modelname: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/deletefloorItem`, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, modeluuid, modelname }), - }); - - if (!response.ok) { - throw new Error("Failed to delete Floor Item"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const deleteFloorItem = async (organization: string, modeluuid: string, modelname: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/deletefloorItem`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, modeluuid, modelname }), + }); + + if (!response.ok) { + throw new Error("Failed to delete Floor Item"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts index ad315e7..efe98fc 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts @@ -1,25 +1,25 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const getFloorItems = async (organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/findfloorItems/${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); - - if (!response.ok) { - throw new Error("Failed to get Floor Items"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const getFloorItems = async (organization: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/findfloorItems/${organization}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error("Failed to get Floor Items"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts index a4fe765..31d5b11 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const setFloorItemApi = async (organization: string, modeluuid: string, modelname: string, position: Object, rotation: Object, modelfileID: string, isLocked: boolean, isVisible: boolean) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setFloorItems`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, modeluuid, modelname, position, rotation, modelfileID, isLocked, isVisible }), - }); - - if (!response.ok) { - throw new Error("Failed to set or update Floor Item"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const setFloorItemApi = async (organization: string, modeluuid: string, modelname: string, position: Object, rotation: Object, modelfileID: string, isLocked: boolean, isVisible: boolean) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setFloorItems`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, modeluuid, modelname, position, rotation, modelfileID, isLocked, isVisible }), + }); + + if (!response.ok) { + throw new Error("Failed to set or update Floor Item"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts index 5dda37c..58f179d 100644 --- a/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts +++ b/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const deleteWallItem = async (organization: string, modeluuid: string, modelname: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteWallItem`, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, modeluuid, modelname }), - }); - - if (!response.ok) { - throw new Error("Failed to delete Wall Item"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const deleteWallItem = async (organization: string, modeluuid: string, modelname: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteWallItem`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, modeluuid, modelname }), + }); + + if (!response.ok) { + throw new Error("Failed to delete Wall Item"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts index eb0a232..73aa0eb 100644 --- a/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts +++ b/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts @@ -1,25 +1,25 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const getWallItems = async (organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/findWallItems/${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); - - if (!response.ok) { - throw new Error("Failed to get Wall Items"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const getWallItems = async (organization: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/findWallItems/${organization}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error("Failed to get Wall Items"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts index e51297b..79bed55 100644 --- a/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts +++ b/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts @@ -1,36 +1,36 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const setWallItem = async ( - organization: string, - modeluuid: string, - modelname: string, - type: string, - csgposition: Object, - csgscale: Object, - position: Object, - quaternion: Object, - scale: Object -) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setWallItems`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, modeluuid, modelname, position, type, csgposition, csgscale, quaternion, scale }), - }); - - if (!response.ok) { - throw new Error("Failed to set or update Wall Item"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const setWallItem = async ( + organization: string, + modeluuid: string, + modelname: string, + type: string, + csgposition: Object, + csgscale: Object, + position: Object, + quaternion: Object, + scale: Object +) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setWallItems`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, modeluuid, modelname, position, type, csgposition, csgscale, quaternion, scale }), + }); + + if (!response.ok) { + throw new Error("Failed to set or update Wall Item"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/camera/getCameraApi.ts b/app/src/services/factoryBuilder/camera/getCameraApi.ts index e8d84d9..35e5e37 100644 --- a/app/src/services/factoryBuilder/camera/getCameraApi.ts +++ b/app/src/services/factoryBuilder/camera/getCameraApi.ts @@ -1,32 +1,32 @@ -import { setCamera } from './setCameraApi'; -import * as THREE from 'three'; - -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const getCamera = async (organization: string, userId: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/getCamera/${organization}/${userId}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); - - if (!response.ok) { - throw new Error("Failed to get Camera position and target"); - } - - const result = await response.json(); - if (result === "user not found") { - return null; - } else { - return result; - } - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +import { setCamera } from './setCameraApi'; +import * as THREE from 'three'; + +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const getCamera = async (organization: string, userId: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/getCamera/${organization}/${userId}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error("Failed to get Camera position and target"); + } + + const result = await response.json(); + if (result === "user not found") { + return null; + } else { + return result; + } + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/camera/setCameraApi.ts b/app/src/services/factoryBuilder/camera/setCameraApi.ts index 46d30e3..7953dc3 100644 --- a/app/src/services/factoryBuilder/camera/setCameraApi.ts +++ b/app/src/services/factoryBuilder/camera/setCameraApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const setCamera = async (organization: string, userId: string, position: Object, target: Object, rotation: Object) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setCamera`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, userId, position, target, rotation }), - }); - - if (!response.ok) { - throw new Error("Failed to set Camera Position and Target"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const setCamera = async (organization: string, userId: string, position: Object, target: Object, rotation: Object) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setCamera`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, userId, position, target, rotation }), + }); + + if (!response.ok) { + throw new Error("Failed to set Camera Position and Target"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/collab/getActiveUsers.ts b/app/src/services/factoryBuilder/collab/getActiveUsers.ts index 30242b6..2d6516b 100644 --- a/app/src/services/factoryBuilder/collab/getActiveUsers.ts +++ b/app/src/services/factoryBuilder/collab/getActiveUsers.ts @@ -1,32 +1,32 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export default async function getActiveUsersData(organization: string) { - const apiUrl = `${url_Backend_dwinzo}/api/v1/activeCameras/${organization}`; - - try { - const response = await fetch(apiUrl, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }); - - if (!response.ok) { - throw new Error(`Error: ${response.status} - ${response.statusText}`); - } - - - if (!response.ok) { - throw new Error("Failed to get active cameras "); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export default async function getActiveUsersData(organization: string) { + const apiUrl = `${url_Backend_dwinzo}/api/v1/activeCameras/${organization}`; + + try { + const response = await fetch(apiUrl, { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }); + + if (!response.ok) { + throw new Error(`Error: ${response.status} - ${response.statusText}`); + } + + + if (!response.ok) { + throw new Error("Failed to get active cameras "); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/collab/getUsersApi.ts b/app/src/services/factoryBuilder/collab/getUsersApi.ts index 808eb76..4fec523 100644 --- a/app/src/services/factoryBuilder/collab/getUsersApi.ts +++ b/app/src/services/factoryBuilder/collab/getUsersApi.ts @@ -1,32 +1,32 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export default async function fetchShareUsers(organization: string) { - const apiUrl = `${url_Backend_dwinzo}/api/v1/findshareUsers?organization=${organization}`; - - try { - const response = await fetch(apiUrl, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }); - - if (!response.ok) { - throw new Error(`Error: ${response.status} - ${response.statusText}`); - } - - - if (!response.ok) { - throw new Error("Failed to get users "); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export default async function fetchShareUsers(organization: string) { + const apiUrl = `${url_Backend_dwinzo}/api/v1/findshareUsers?organization=${organization}`; + + try { + const response = await fetch(apiUrl, { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }); + + if (!response.ok) { + throw new Error(`Error: ${response.status} - ${response.statusText}`); + } + + + if (!response.ok) { + throw new Error("Failed to get users "); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/collab/giveCollabAccess.ts b/app/src/services/factoryBuilder/collab/giveCollabAccess.ts index b70b4f7..07f68a8 100644 --- a/app/src/services/factoryBuilder/collab/giveCollabAccess.ts +++ b/app/src/services/factoryBuilder/collab/giveCollabAccess.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export default async function giveCollabAccess(email: string, isShare: boolean, organization: string) { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/shareUser`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ email, isShare, organization }), - }); - - if (!response.ok) { - throw new Error("Failed to set Camera Position and Target"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export default async function giveCollabAccess(email: string, isShare: boolean, organization: string) { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/shareUser`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ email, isShare, organization }), + }); + + if (!response.ok) { + throw new Error("Failed to set Camera Position and Target"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/environment/findEnvironment.ts b/app/src/services/factoryBuilder/environment/findEnvironment.ts index ff81b07..525bdda 100644 --- a/app/src/services/factoryBuilder/environment/findEnvironment.ts +++ b/app/src/services/factoryBuilder/environment/findEnvironment.ts @@ -1,32 +1,32 @@ -import { setEnvironment } from './setEnvironment'; - -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const findEnvironment = async (organization: string, userId: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/findEnvironments/${organization}/${userId}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); - - if (!response.ok) { - throw new Error("Failed to get wall and roof visibility"); - } - - const result = await response.json(); - if (result === "user not found") { - const userpos = setEnvironment(organization, userId, false, false, false); - return userpos; - } else { - return result; - } - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +import { setEnvironment } from './setEnvironment'; + +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const findEnvironment = async (organization: string, userId: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/findEnvironments/${organization}/${userId}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error("Failed to get wall and roof visibility"); + } + + const result = await response.json(); + if (result === "user not found") { + const userpos = setEnvironment(organization, userId, false, false, false); + return userpos; + } else { + return result; + } + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/environment/setEnvironment.ts b/app/src/services/factoryBuilder/environment/setEnvironment.ts index 072b7bb..070146f 100644 --- a/app/src/services/factoryBuilder/environment/setEnvironment.ts +++ b/app/src/services/factoryBuilder/environment/setEnvironment.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const setEnvironment = async (organization: string, userId: string, wallVisibility: Boolean, roofVisibility: Boolean, shadowVisibility: Boolean) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setEvironments`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, userId, wallVisibility, roofVisibility, shadowVisibility }), - }); - - if (!response.ok) { - throw new Error("Failed to set wall and roof visibility"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const setEnvironment = async (organization: string, userId: string, wallVisibility: Boolean, roofVisibility: Boolean, shadowVisibility: Boolean) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setEvironments`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, userId, wallVisibility, roofVisibility, shadowVisibility }), + }); + + if (!response.ok) { + throw new Error("Failed to set wall and roof visibility"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/lines/deleteLayerApi.ts b/app/src/services/factoryBuilder/lines/deleteLayerApi.ts index 54160c8..4f81271 100644 --- a/app/src/services/factoryBuilder/lines/deleteLayerApi.ts +++ b/app/src/services/factoryBuilder/lines/deleteLayerApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const deleteLayer = async (organization: string, layer: number) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteLayer`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, layer }), - }); - - if (!response.ok) { - throw new Error("Failed to delete line"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const deleteLayer = async (organization: string, layer: number) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteLayer`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, layer }), + }); + + if (!response.ok) { + throw new Error("Failed to delete line"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/lines/deleteLineApi.ts b/app/src/services/factoryBuilder/lines/deleteLineApi.ts index 64a76c4..09f1584 100644 --- a/app/src/services/factoryBuilder/lines/deleteLineApi.ts +++ b/app/src/services/factoryBuilder/lines/deleteLineApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const deleteLineApi = async (organization: string, line: Object) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteLine`, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, line }), - }); - - if (!response.ok) { - throw new Error("Failed to delete line"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const deleteLineApi = async (organization: string, line: Object) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteLine`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, line }), + }); + + if (!response.ok) { + throw new Error("Failed to delete line"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/lines/deletePointApi.ts b/app/src/services/factoryBuilder/lines/deletePointApi.ts index 60a6fd4..cc31589 100644 --- a/app/src/services/factoryBuilder/lines/deletePointApi.ts +++ b/app/src/services/factoryBuilder/lines/deletePointApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const deletePointApi = async (organization: string, uuid: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/deletePoint`, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, uuid }), - }); - - if (!response.ok) { - throw new Error("Failed to delete point"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const deletePointApi = async (organization: string, uuid: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/deletePoint`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, uuid }), + }); + + if (!response.ok) { + throw new Error("Failed to delete point"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/lines/getLinesApi.ts b/app/src/services/factoryBuilder/lines/getLinesApi.ts index 00c86a9..72450b4 100644 --- a/app/src/services/factoryBuilder/lines/getLinesApi.ts +++ b/app/src/services/factoryBuilder/lines/getLinesApi.ts @@ -1,25 +1,25 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const getLines = async (organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/findLines/${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); - - if (!response.ok) { - throw new Error("Failed to get Lines"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const getLines = async (organization: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/findLines/${organization}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error("Failed to get Lines"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/lines/setLineApi.ts b/app/src/services/factoryBuilder/lines/setLineApi.ts index 269c26d..43c50eb 100644 --- a/app/src/services/factoryBuilder/lines/setLineApi.ts +++ b/app/src/services/factoryBuilder/lines/setLineApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const setLine = async (organization: string, layer: number, line: Object, type: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, layer, line, type }), - }); - - if (!response.ok) { - throw new Error("Failed to set line"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const setLine = async (organization: string, layer: number, line: Object, type: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, layer, line, type }), + }); + + if (!response.ok) { + throw new Error("Failed to set line"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/lines/updatePointApi.ts b/app/src/services/factoryBuilder/lines/updatePointApi.ts index 8e4a93a..a7ed0c3 100644 --- a/app/src/services/factoryBuilder/lines/updatePointApi.ts +++ b/app/src/services/factoryBuilder/lines/updatePointApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const updatePoint = async (organization: string, position: Object, uuid: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/updatePoint`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ organization, position, uuid }), - }); - - if (!response.ok) { - throw new Error("Failed to update point"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const updatePoint = async (organization: string, position: Object, uuid: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/updatePoint`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, position, uuid }), + }); + + if (!response.ok) { + throw new Error("Failed to update point"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/mqtt/mqttEvents.ts b/app/src/services/factoryBuilder/mqtt/mqttEvents.ts index fc009be..cd79484 100644 --- a/app/src/services/factoryBuilder/mqtt/mqttEvents.ts +++ b/app/src/services/factoryBuilder/mqtt/mqttEvents.ts @@ -1,48 +1,48 @@ -import React, { useEffect } from "react"; -import mqtt from "mqtt"; -import { useDrieUIValue } from "../../../store/store"; - -const MqttEvents = () => { - const { setTouch, setTemperature, setHumidity } = useDrieUIValue(); - useEffect(() => { - - const client = mqtt.connect("ws://192.168.0.192:1884", { - username: "gabby", - password: "gabby" - }); - - client.subscribe("touch"); - client.subscribe("temperature"); - client.subscribe("humidity"); - - const handleMessage = (topic: string, message: any) => { - const value = message.toString(); - - if (topic === "touch") { - setTouch(value); - } else if (topic === "temperature") { - setTemperature(parseFloat(value)); - } else if (topic === "humidity") { - setHumidity(parseFloat(value)); - } - }; - - client.on("message", handleMessage); - - client.on("error", (err) => { - console.error("MQTT Connection Error:", err); - }); - - client.on("close", () => { - console.log("MQTT Connection Closed"); - }); - - return () => { - client.end(); - }; - }, [setTouch, setTemperature, setHumidity]); - - return null; -}; - -export default MqttEvents; +import React, { useEffect } from "react"; +import mqtt from "mqtt"; +import { useDrieUIValue } from "../../../store/store"; + +const MqttEvents = () => { + const { setTouch, setTemperature, setHumidity } = useDrieUIValue(); + useEffect(() => { + + const client = mqtt.connect("ws://192.168.0.192:1884", { + username: "gabby", + password: "gabby" + }); + + client.subscribe("touch"); + client.subscribe("temperature"); + client.subscribe("humidity"); + + const handleMessage = (topic: string, message: any) => { + const value = message.toString(); + + if (topic === "touch") { + setTouch(value); + } else if (topic === "temperature") { + setTemperature(parseFloat(value)); + } else if (topic === "humidity") { + setHumidity(parseFloat(value)); + } + }; + + client.on("message", handleMessage); + + client.on("error", (err) => { + console.error("MQTT Connection Error:", err); + }); + + client.on("close", () => { + console.log("MQTT Connection Closed"); + }); + + return () => { + client.end(); + }; + }, [setTouch, setTemperature, setHumidity]); + + return null; +}; + +export default MqttEvents; diff --git a/app/src/services/factoryBuilder/signInSignUp/signInApi.ts b/app/src/services/factoryBuilder/signInSignUp/signInApi.ts index be608c0..c2b32c5 100644 --- a/app/src/services/factoryBuilder/signInSignUp/signInApi.ts +++ b/app/src/services/factoryBuilder/signInSignUp/signInApi.ts @@ -1,22 +1,22 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const signIn = async (email: string, password: Object, organization: Object) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/login`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ email, password, organization }), - }); - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - return { error: error.message }; - } else { - return { error: "An unknown error occurred" }; - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const signInApi = async (email: string, password: Object, organization: Object) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/login`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ email, password, organization }), + }); + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + return { error: error.message }; + } else { + return { error: "An unknown error occurred" }; + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts b/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts index 87ded2b..ac55948 100644 --- a/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts +++ b/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const signUp = async (userName: string, email: string, password: Object, organization: Object) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/signup`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ userName, email, password, organization }), - }); - - if (!response.ok) { - throw new Error("Failed to signUp"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const signUpApi = async (userName: string, email: string, password: Object, organization: Object) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/signup`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ userName, email, password, organization }), + }); + + if (!response.ok) { + throw new Error("Failed to signUpApi"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/webWorkers/assetManagerWorker.js b/app/src/services/factoryBuilder/webWorkers/assetManagerWorker.js index db17487..4ccdbf5 100644 --- a/app/src/services/factoryBuilder/webWorkers/assetManagerWorker.js +++ b/app/src/services/factoryBuilder/webWorkers/assetManagerWorker.js @@ -1,51 +1,51 @@ -import * as THREE from 'three'; -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; -import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; - -const loader = new GLTFLoader(); -const dracoLoader = new DRACOLoader(); -dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); -loader.setDRACOLoader(dracoLoader); - -onmessage = (event) => { - const { floorItems, cameraPosition, uuids, renderDistance } = event.data; - if (!floorItems) return - - const toAdd = []; - const toRemove = []; - - const cameraPos = new THREE.Vector3(cameraPosition.x, cameraPosition.y, cameraPosition.z); - - // Check for items to be added - floorItems.forEach((item) => { - const itemPosition = new THREE.Vector3(...item.position); - const distance = cameraPos.distanceTo(itemPosition); - - if (distance <= renderDistance && !uuids.includes(item.modeluuid)) { - toAdd.push(item); - } - }); - - // Sort the toAdd array based on distance (closest first) - toAdd.sort((a, b) => { - const aDistance = cameraPos.distanceTo(new THREE.Vector3(...a.position)); - const bDistance = cameraPos.distanceTo(new THREE.Vector3(...b.position)); - return aDistance - bDistance; - }); - - // Check for items to be removed - uuids.forEach((uuid) => { - const floorItem = floorItems.find((item) => item.modeluuid === uuid); - if (floorItem) { - const itemPosition = new THREE.Vector3(...floorItem.position); - const distance = cameraPos.distanceTo(itemPosition); - - if (distance > renderDistance) { - toRemove.push(uuid); - } - } - }); - - // Send the result back to the main thread - postMessage({ toAdd, toRemove }); -}; +import * as THREE from 'three'; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; + +const loader = new GLTFLoader(); +const dracoLoader = new DRACOLoader(); +dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); +loader.setDRACOLoader(dracoLoader); + +onmessage = (event) => { + const { floorItems, cameraPosition, uuids, renderDistance } = event.data; + if (!floorItems) return + + const toAdd = []; + const toRemove = []; + + const cameraPos = new THREE.Vector3(cameraPosition.x, cameraPosition.y, cameraPosition.z); + + // Check for items to be added + floorItems.forEach((item) => { + const itemPosition = new THREE.Vector3(...item.position); + const distance = cameraPos.distanceTo(itemPosition); + + if (distance <= renderDistance && !uuids.includes(item.modeluuid)) { + toAdd.push(item); + } + }); + + // Sort the toAdd array based on distance (closest first) + toAdd.sort((a, b) => { + const aDistance = cameraPos.distanceTo(new THREE.Vector3(...a.position)); + const bDistance = cameraPos.distanceTo(new THREE.Vector3(...b.position)); + return aDistance - bDistance; + }); + + // Check for items to be removed + uuids.forEach((uuid) => { + const floorItem = floorItems.find((item) => item.modeluuid === uuid); + if (floorItem) { + const itemPosition = new THREE.Vector3(...floorItem.position); + const distance = cameraPos.distanceTo(itemPosition); + + if (distance > renderDistance) { + toRemove.push(uuid); + } + } + }); + + // Send the result back to the main thread + postMessage({ toAdd, toRemove }); +}; diff --git a/app/src/services/factoryBuilder/webWorkers/gltfLoaderWorker.js b/app/src/services/factoryBuilder/webWorkers/gltfLoaderWorker.js index a051538..effa8b3 100644 --- a/app/src/services/factoryBuilder/webWorkers/gltfLoaderWorker.js +++ b/app/src/services/factoryBuilder/webWorkers/gltfLoaderWorker.js @@ -1,38 +1,38 @@ -import * as THREE from 'three'; -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; -import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; -import { retrieveGLTF, storeGLTF } from '../../../components/scene/indexDB/idbUtils'; - -const loader = new GLTFLoader(); -const dracoLoader = new DRACOLoader(); -dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); -loader.setDRACOLoader(dracoLoader); -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; - -onmessage = async (event) => { - const { floorItems } = event.data; - - const uniqueItems = floorItems.filter((item, index, self) => - index === self.findIndex((t) => t.modelfileID === item.modelfileID) - ); - - for (const item of uniqueItems) { - const modelID = item.modelfileID; - const indexedDBModel = await retrieveGLTF(modelID); - - let modelBlob; - if (indexedDBModel) { - modelBlob = indexedDBModel; - const message = "gltfLoaded"; - postMessage({ message, modelID, modelBlob }); - } else { - const modelUrl = `${url_Backend_dwinzo}/api/v1/AssetFile/${modelID}`; - const modelBlob = await fetch(modelUrl).then((res) => res.blob()); - await storeGLTF(modelID, modelBlob); - const message = "gltfLoaded"; - postMessage({ message, modelID, modelBlob }); - } - } - - postMessage({ message: 'done' }) -}; +import * as THREE from 'three'; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; +import { retrieveGLTF, storeGLTF } from '../../../components/scene/indexDB/idbUtils'; + +const loader = new GLTFLoader(); +const dracoLoader = new DRACOLoader(); +dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); +loader.setDRACOLoader(dracoLoader); +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; + +onmessage = async (event) => { + const { floorItems } = event.data; + + const uniqueItems = floorItems.filter((item, index, self) => + index === self.findIndex((t) => t.modelfileID === item.modelfileID) + ); + + for (const item of uniqueItems) { + const modelID = item.modelfileID; + const indexedDBModel = await retrieveGLTF(modelID); + + let modelBlob; + if (indexedDBModel) { + modelBlob = indexedDBModel; + const message = "gltfLoaded"; + postMessage({ message, modelID, modelBlob }); + } else { + const modelUrl = `${url_Backend_dwinzo}/api/v1/AssetFile/${modelID}`; + const modelBlob = await fetch(modelUrl).then((res) => res.blob()); + await storeGLTF(modelID, modelBlob); + const message = "gltfLoaded"; + postMessage({ message, modelID, modelBlob }); + } + } + + postMessage({ message: 'done' }) +}; diff --git a/app/src/services/factoryBuilder/webWorkers/shadowWorker.js b/app/src/services/factoryBuilder/webWorkers/shadowWorker.js index 67bd52a..25a6f51 100644 --- a/app/src/services/factoryBuilder/webWorkers/shadowWorker.js +++ b/app/src/services/factoryBuilder/webWorkers/shadowWorker.js @@ -1,11 +1,11 @@ -import * as THREE from 'three'; - -onmessage = (event) => { - const { controlsTarget, sunPosition, offsetDistance } = event.data; - - const lightPosition = new THREE.Vector3() - .copy(controlsTarget) - .addScaledVector(new THREE.Vector3().copy(sunPosition).normalize(), offsetDistance); - - postMessage({ lightPosition, controlsTarget }); +import * as THREE from 'three'; + +onmessage = (event) => { + const { controlsTarget, sunPosition, offsetDistance } = event.data; + + const lightPosition = new THREE.Vector3() + .copy(controlsTarget) + .addScaledVector(new THREE.Vector3().copy(sunPosition).normalize(), offsetDistance); + + postMessage({ lightPosition, controlsTarget }); }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/zones/deleteZoneApi.ts b/app/src/services/factoryBuilder/zones/deleteZoneApi.ts index 25f7fcf..2ba5156 100644 --- a/app/src/services/factoryBuilder/zones/deleteZoneApi.ts +++ b/app/src/services/factoryBuilder/zones/deleteZoneApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const deleteZonesApi = async (userId: string, organization: string, zoneId: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ userId, organization, zoneId }), - }); - - if (!response.ok) { - throw new Error("Failed to delete zone"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const deleteZonesApi = async (userId: string, organization: string, zoneId: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ userId, organization, zoneId }), + }); + + if (!response.ok) { + throw new Error("Failed to delete zone"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/zones/getZonesApi.ts b/app/src/services/factoryBuilder/zones/getZonesApi.ts index ef16874..be7741c 100644 --- a/app/src/services/factoryBuilder/zones/getZonesApi.ts +++ b/app/src/services/factoryBuilder/zones/getZonesApi.ts @@ -1,25 +1,25 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const getZonesApi = async (organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/findZones/${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); - - // if (!response.ok) { - // throw new Error("Failed to get Zones"); - // } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const getZonesApi = async (organization: string) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v2/findZones/${organization}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + // if (!response.ok) { + // throw new Error("Failed to get Zones"); + // } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/services/factoryBuilder/zones/setZonesApi.ts b/app/src/services/factoryBuilder/zones/setZonesApi.ts index a1fd3ed..c19e91a 100644 --- a/app/src/services/factoryBuilder/zones/setZonesApi.ts +++ b/app/src/services/factoryBuilder/zones/setZonesApi.ts @@ -1,26 +1,26 @@ -let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; - -export const setZonesApi = async (userId: string, organization: string, zoneData: any) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ userId, organization, zoneData }), - }); - - if (!response.ok) { - throw new Error("Failed to set zone"); - } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } - } +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const setZonesApi = async (userId: string, organization: string, zoneData: any) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ userId, organization, zoneData }), + }); + + if (!response.ok) { + throw new Error("Failed to set zone"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } }; \ No newline at end of file diff --git a/app/src/setupTests.ts b/app/src/setupTests.ts index 8f2609b..141e479 100644 --- a/app/src/setupTests.ts +++ b/app/src/setupTests.ts @@ -1,5 +1,5 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom'; diff --git a/app/src/store/store.ts b/app/src/store/store.ts index f14b808..0cca1fe 100644 --- a/app/src/store/store.ts +++ b/app/src/store/store.ts @@ -1,336 +1,402 @@ -import * as THREE from "three"; -import * as Types from '../types/world/worldTypes'; -import { create } from "zustand"; -import { io } from "socket.io-client"; - -export const useSocketStore = create((set: any, get: any) => ({ - socket: null, - initializeSocket: (email: any) => { - const existingSocket = get().socket; - if (existingSocket) { - return; - } - - const socket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/`, { - reconnection: false, - auth: { email } - }); - - set({ socket }); - }, - disconnectSocket: () => { - set((state: any) => { - state.socket?.disconnect(); - return { socket: null }; - }); - } -})); - -export const useOrganization = create((set: any) => ({ - organization: "", - setOrganization: (x: any) => set(() => ({ organization: x })), -})); - -export const useToggleView = create((set: any) => ({ - toggleView: false, - setToggleView: (x: any) => set(() => ({ toggleView: x })), -})); - -export const useUpdateScene = create((set: any) => ({ - updateScene: false, - setUpdateScene: (x: any) => set(() => ({ updateScene: x })), -})); - -export const useWalls = create((set: any) => ({ - walls: [], - setWalls: (x: any) => set(() => ({ walls: x })), -})); - -export const useZones = create((set: any) => ({ - zones: [], - setZones: (x: any) => set(() => ({ zones: x })), -})); - -interface ZonePointsState { - zonePoints: THREE.Vector3[]; - setZonePoints: (points: THREE.Vector3[]) => void; -} - -export const useZonePoints = create((set) => ({ - zonePoints: [], - setZonePoints: (points) => set({ zonePoints: points }), -})); - -export const useSelectedItem = create((set: any) => ({ - selectedItem: { name: "", id: "" }, - setSelectedItem: (x: any) => set(() => ({ selectedItem: x })), -})); - -export const useSelectedAssets = create((set: any) => ({ - selectedAssets: [], - setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })), -})); - -export const useLayers = create((set: any) => ({ - Layers: 1, - setLayers: (x: any) => set(() => ({ Layers: x })), -})); - -export const useCamPosition = create((set: any) => ({ - camPosition: { x: undefined, y: undefined, z: undefined }, - setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }), -})); - -export const useMenuVisible = create((set: any) => ({ - menuVisible: false, - setMenuVisible: (x: any) => set(() => ({ menuVisible: x })), -})); - -export const useDeleteModels = create((set: any) => ({ - deleteModels: false, - setDeleteModels: (x: any) => set(() => ({ deleteModels: x })), -})); - -export const useToolMode = create((set: any) => ({ - toolMode: null, - setToolMode: (x: any) => set(() => ({ toolMode: x })), -})); - -export const useNewLines = create((set: any) => ({ - newLines: [], - setNewLines: (x: any) => set(() => ({ newLines: x })), -})); - -export const useDeletedLines = create((set: any) => ({ - deletedLines: [], - setDeletedLines: (x: any) => set(() => ({ deletedLines: x })), -})); - -export const useMovePoint = create((set: any) => ({ - movePoint: false, - setMovePoint: (x: any) => set(() => ({ movePoint: x })), -})); - -export const useTransformMode = create((set: any) => ({ - transformMode: null, - setTransformMode: (x: any) => set(() => ({ transformMode: x })), -})); - -export const useDeletePointOrLine = create((set: any) => ({ - deletePointOrLine: false, - setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })), -})); - -export const useFloorItems = create((set: any) => ({ - floorItems: null, - setFloorItems: (callback: any) => - set((state: any) => ({ - floorItems: - typeof callback === "function" - ? callback(state.floorItems) - : callback, - })), -})); - -export const useWallItems = create((set: any) => ({ - wallItems: [], - setWallItems: (callback: any) => - set((state: any) => ({ - wallItems: - typeof callback === "function" - ? callback(state.wallItems) - : callback, - })), -})); - -export const useSelectedWallItem = create((set: any) => ({ - selectedWallItem: null, - setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })), -})); - -export const useselectedFloorItem = create((set: any) => ({ - selectedFloorItem: null, - setselectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })), -})); - -export const useDeletableFloorItem = create((set: any) => ({ - deletableFloorItem: null, - setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })), -})); - -export const useSetScale = create((set: any) => ({ - scale: null, - setScale: (x: any) => set(() => ({ scale: x })), -})); - -export const useRoofVisibility = create((set: any) => ({ - roofVisibility: false, - setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })), -})); - -export const useWallVisibility = create((set: any) => ({ - wallVisibility: false, - setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })), -})); - -export const useShadows = create((set: any) => ({ - shadows: false, - setShadows: (x: any) => set(() => ({ shadows: x })), -})); - -export const useSunPosition = create((set: any) => ({ - sunPosition: { x: undefined, y: undefined, z: undefined }, - setSunPosition: (newSuntPosition: any) => set({ sunPosition: newSuntPosition }), -})); - -export const useRemoveLayer = create((set: any) => ({ - removeLayer: false, - setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })), -})); - -export const useRemovedLayer = create((set: any) => ({ - removedLayer: null, - setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })), -})); - -export const useActiveLayer = create((set: any) => ({ - activeLayer: 1, - setActiveLayer: (x: any) => set({ activeLayer: x }), -})); - -export const useResetCamera = create((set: any) => ({ - resetCamera: false, - setResetCamera: (x: any) => set({ resetCamera: x }), -})); - -export const useAddAction = create((set: any) => ({ - addAction: null, - setAddAction: (x: any) => set({ addAction: x }), -})); - -export const useActiveTool = create((set: any) => ({ - activeTool: "Cursor", - setActiveTool: (x: any) => set({ activeTool: x }), -})); - -export const use2DUndoRedo = create((set: any) => ({ - is2DUndoRedo: null, - set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }), -})) - -export const useElevation = create((set: any) => ({ - elevation: 45, - setElevation: (x: any) => set({ elevation: x }), -})); - -export const useAzimuth = create((set: any) => ({ - azimuth: -160, - setAzimuth: (x: any) => set({ azimuth: x }), -})); - -export const useRenderDistance = create((set: any) => ({ - renderDistance: 50, - setRenderDistance: (x: any) => set({ renderDistance: x }), -})); - -export const useCamMode = create((set: any) => ({ - camMode: "ThirdPerson", - setCamMode: (x: any) => set({ camMode: x }), -})); - -export const useUserName = create((set: any) => ({ - userName: "", - setUserName: (x: any) => set({ userName: x }), -})); - -export const useObjectPosition = create((set: any) => ({ - objectPosition: { x: undefined, y: undefined, z: undefined }, - setObjectPosition: (newObjectPosition: any) => set({ objectPosition: newObjectPosition }), -})); - -export const useObjectScale = create((set: any) => ({ - objectScale: { x: undefined, y: undefined, z: undefined }, - setObjectScale: (newObjectScale: any) => set({ objectScale: newObjectScale }), -})); - -export const useObjectRotation = create((set: any) => ({ - objectRotation: { x: undefined, y: undefined, z: undefined }, - setObjectRotation: (newObjectRotation: any) => set({ objectRotation: newObjectRotation }), -})); - -export const useDrieTemp = create((set: any) => ({ - drieTemp: undefined, - setDrieTemp: (x: any) => set({ drieTemp: x }), -})); - -export const useActiveUsers = create((set: any) => ({ - activeUsers: [], - setActiveUsers: (x: any) => set({ activeUsers: x }), -})); - -export const useDrieUIValue = create((set: any) => ({ - drieUIValue: { touch: null, temperature: null, humidity: null }, - - setDrieUIValue: (x: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })), - - setTouch: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, touch: value } })), - setTemperature: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, temperature: value } })), - setHumidity: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, humidity: value } })), -})); - -export const useDrawMaterialPath = create((set: any) => ({ - drawMaterialPath: false, - setDrawMaterialPath: (x: any) => set({ drawMaterialPath: x }), -})); - -export const useSelectedEventSphere = create((set: any) => ({ - selectedEventSphere: undefined, - setSelectedEventSphere: (x: any) => set({ selectedEventSphere: x }), -})); - -export const useSelectedPath = create((set: any) => ({ - selectedPath: undefined, - setSelectedPath: (x: any) => set({ selectedPath: x }), -})); - -export const useSimulationPaths = create((set) => ({ - simulationPaths: [], - setSimulationPaths: (paths) => set({ simulationPaths: paths }), -})); - -export const useConnections = create((set) => ({ - connections: [], - - setConnections: (connections) => set({ connections }), - - addConnection: (newConnection) => - set((state) => ({ - connections: [...state.connections, newConnection], - })), - - removeConnection: (fromUUID, toUUID) => - set((state) => ({ - connections: state.connections - .map((connection) => - connection.fromUUID === fromUUID - ? { - ...connection, - toConnections: connection.toConnections.filter( - (to) => to.toUUID !== toUUID - ), - } - : connection - ) - .filter((connection) => connection.toConnections.length > 0), - })), -})); - -export const useIsConnecting = create((set: any) => ({ - isConnecting: false, - setIsConnecting: (x: any) => set({ isConnecting: x }), -})); - -export const useStartSimulation = create((set: any) => ({ - startSimulation: false, - setStartSimulation: (x: any) => set({ startSimulation: x }), +import * as THREE from "three"; +import * as Types from '../types/world/worldTypes'; +import { create } from "zustand"; +import { io } from "socket.io-client"; + +export const useSocketStore = create((set: any, get: any) => ({ + socket: null, + initializeSocket: (email: any) => { + const existingSocket = get().socket; + if (existingSocket) { + return; + } + + const socket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/`, { + reconnection: false, + auth: { email } + }); + + set({ socket }); + }, + disconnectSocket: () => { + set((state: any) => { + state.socket?.disconnect(); + return { socket: null }; + }); + } +})); + +export const useOrganization = create((set: any) => ({ + organization: "", + setOrganization: (x: any) => set(() => ({ organization: x })), +})); + +export const useToggleView = create((set: any) => ({ + toggleView: false, + setToggleView: (x: any) => set(() => ({ toggleView: x })), +})); + +export const useUpdateScene = create((set: any) => ({ + updateScene: false, + setUpdateScene: (x: any) => set(() => ({ updateScene: x })), +})); + +export const useWalls = create((set: any) => ({ + walls: [], + setWalls: (x: any) => set(() => ({ walls: x })), +})); + +export const useZones = create((set: any) => ({ + zones: [], + setZones: (x: any) => set(() => ({ zones: x })), +})); + +interface ZonePointsState { + zonePoints: THREE.Vector3[]; + setZonePoints: (points: THREE.Vector3[]) => void; +} + +export const useZonePoints = create((set) => ({ + zonePoints: [], + setZonePoints: (points) => set({ zonePoints: points }), +})); + +export const useSelectedItem = create((set: any) => ({ + selectedItem: { name: "", id: "" }, + setSelectedItem: (x: any) => set(() => ({ selectedItem: x })), +})); + +export const useSelectedAssets = create((set: any) => ({ + selectedAssets: [], + setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })), +})); + +export const useLayers = create((set: any) => ({ + Layers: 1, + setLayers: (x: any) => set(() => ({ Layers: x })), +})); + +export const useCamPosition = create((set: any) => ({ + camPosition: { x: undefined, y: undefined, z: undefined }, + setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }), +})); + +export const useMenuVisible = create((set: any) => ({ + menuVisible: false, + setMenuVisible: (x: any) => set(() => ({ menuVisible: x })), +})); + +export const useDeleteModels = create((set: any) => ({ + deleteModels: false, + setDeleteModels: (x: any) => set(() => ({ deleteModels: x })), +})); + +export const useToolMode = create((set: any) => ({ + toolMode: null, + setToolMode: (x: any) => set(() => ({ toolMode: x })), +})); + +export const useNewLines = create((set: any) => ({ + newLines: [], + setNewLines: (x: any) => set(() => ({ newLines: x })), +})); + +export const useDeletedLines = create((set: any) => ({ + deletedLines: [], + setDeletedLines: (x: any) => set(() => ({ deletedLines: x })), +})); + +export const useMovePoint = create((set: any) => ({ + movePoint: false, + setMovePoint: (x: any) => set(() => ({ movePoint: x })), +})); + +export const useTransformMode = create((set: any) => ({ + transformMode: null, + setTransformMode: (x: any) => set(() => ({ transformMode: x })), +})); + +export const useDeletePointOrLine = create((set: any) => ({ + deletePointOrLine: false, + setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })), +})); + +export const useFloorItems = create((set: any) => ({ + floorItems: null, + setFloorItems: (callback: any) => + set((state: any) => ({ + floorItems: + typeof callback === "function" + ? callback(state.floorItems) + : callback, + })), +})); + +export const useWallItems = create((set: any) => ({ + wallItems: [], + setWallItems: (callback: any) => + set((state: any) => ({ + wallItems: + typeof callback === "function" + ? callback(state.wallItems) + : callback, + })), +})); + +export const useSelectedWallItem = create((set: any) => ({ + selectedWallItem: null, + setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })), +})); + +export const useselectedFloorItem = create((set: any) => ({ + selectedFloorItem: null, + setselectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })), +})); + +export const useDeletableFloorItem = create((set: any) => ({ + deletableFloorItem: null, + setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })), +})); + +export const useSetScale = create((set: any) => ({ + scale: null, + setScale: (x: any) => set(() => ({ scale: x })), +})); + +export const useRoofVisibility = create((set: any) => ({ + roofVisibility: false, + setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })), +})); + +export const useWallVisibility = create((set: any) => ({ + wallVisibility: false, + setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })), +})); + +export const useShadows = create((set: any) => ({ + shadows: false, + setShadows: (x: any) => set(() => ({ shadows: x })), +})); + +export const useSunPosition = create((set: any) => ({ + sunPosition: { x: undefined, y: undefined, z: undefined }, + setSunPosition: (newSuntPosition: any) => set({ sunPosition: newSuntPosition }), +})); + +export const useRemoveLayer = create((set: any) => ({ + removeLayer: false, + setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })), +})); + +export const useRemovedLayer = create((set: any) => ({ + removedLayer: null, + setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })), +})); + +export const useActiveLayer = create((set: any) => ({ + activeLayer: 1, + setActiveLayer: (x: any) => set({ activeLayer: x }), +})); + +export const useResetCamera = create((set: any) => ({ + resetCamera: false, + setResetCamera: (x: any) => set({ resetCamera: x }), +})); + +export const useAddAction = create((set: any) => ({ + addAction: null, + setAddAction: (x: any) => set({ addAction: x }), +})); + +export const useActiveTool = create((set: any) => ({ + activeTool: "Cursor", + setActiveTool: (x: any) => set({ activeTool: x }), +})); + +export const use2DUndoRedo = create((set: any) => ({ + is2DUndoRedo: null, + set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }), +})) + +export const useElevation = create((set: any) => ({ + elevation: 45, + setElevation: (x: any) => set({ elevation: x }), +})); + +export const useAzimuth = create((set: any) => ({ + azimuth: -160, + setAzimuth: (x: any) => set({ azimuth: x }), +})); + +export const useRenderDistance = create((set: any) => ({ + renderDistance: 50, + setRenderDistance: (x: any) => set({ renderDistance: x }), +})); + +export const useCamMode = create((set: any) => ({ + camMode: "ThirdPerson", + setCamMode: (x: any) => set({ camMode: x }), +})); + +export const useUserName = create((set: any) => ({ + userName: "", + setUserName: (x: any) => set({ userName: x }), +})); + +export const useObjectPosition = create((set: any) => ({ + objectPosition: { x: undefined, y: undefined, z: undefined }, + setObjectPosition: (newObjectPosition: any) => set({ objectPosition: newObjectPosition }), +})); + +export const useObjectScale = create((set: any) => ({ + objectScale: { x: undefined, y: undefined, z: undefined }, + setObjectScale: (newObjectScale: any) => set({ objectScale: newObjectScale }), +})); + +export const useObjectRotation = create((set: any) => ({ + objectRotation: { x: undefined, y: undefined, z: undefined }, + setObjectRotation: (newObjectRotation: any) => set({ objectRotation: newObjectRotation }), +})); + +export const useDrieTemp = create((set: any) => ({ + drieTemp: undefined, + setDrieTemp: (x: any) => set({ drieTemp: x }), +})); + +export const useActiveUsers = create((set: any) => ({ + activeUsers: [], + setActiveUsers: (x: any) => set({ activeUsers: x }), +})); + +export const useDrieUIValue = create((set: any) => ({ + drieUIValue: { touch: null, temperature: null, humidity: null }, + + setDrieUIValue: (x: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })), + + setTouch: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, touch: value } })), + setTemperature: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, temperature: value } })), + setHumidity: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, humidity: value } })), +})); + +export const useDrawMaterialPath = create((set: any) => ({ + drawMaterialPath: false, + setDrawMaterialPath: (x: any) => set({ drawMaterialPath: x }), +})); + +export const useSelectedActionSphere = create((set: any) => ({ + selectedActionSphere: undefined, + setSelectedActionSphere: (x: any) => set({ selectedActionSphere: x }), +})); + +export const useSelectedPath = create((set: any) => ({ + selectedPath: undefined, + setSelectedPath: (x: any) => set({ selectedPath: x }), +})); + +interface Path { + modeluuid: string; + modelName: string; + points: { + uuid: string; + position: [number, number, number]; + rotation: [number, number, number]; + actions: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; + triggers: { uuid: string; type: string; isUsed: boolean }[] | []; + }[]; + pathPosition: [number, number, number]; + pathRotation: [number, number, number]; + speed: number; +} + +interface SimulationPathsStore { + simulationPaths: Path[]; + setSimulationPaths: (paths: Path[]) => void; +} + +export const useSimulationPaths = create((set) => ({ + simulationPaths: [], + setSimulationPaths: (paths) => set({ simulationPaths: paths }), +})); + + +// interface Point { +// uuid: string; +// position: [number, number, number]; +// rotation: [number, number, number]; +// event: { +// uuid: string; +// type: string; +// material: string; +// delay: number | string; +// spawnInterval: number | string; +// isUsed: boolean; +// }; +// trigger: { +// uuid: string; +// type: string; +// isUsed: boolean; +// }; +// } + +// interface Process { +// processId: string; +// processName: string; +// points: Point[]; +// pathPosition: [number, number, number]; +// pathRotation: [number, number, number]; +// speed: number; +// isUsed: boolean; +// } + +// interface Path { +// modeluuid: string; +// processes: Process[]; +// } + +// interface SimulationPathsStore { +// simulationPaths: Path[]; +// setSimulationPaths: (paths: Path[]) => void; +// } + +// export const useSimulationPaths = create((set) => ({ +// simulationPaths: [], +// setSimulationPaths: (paths) => set({ simulationPaths: paths }), +// })); + + +export const useConnections = create((set) => ({ + connections: [], + + setConnections: (connections) => set({ connections }), + + addConnection: (newConnection) => + set((state) => ({ + connections: [...state.connections, newConnection], + })), + + removeConnection: (fromUUID, toUUID) => + set((state) => ({ + connections: state.connections + .map((connection) => + connection.fromUUID === fromUUID + ? { + ...connection, + toConnections: connection.toConnections.filter( + (to) => to.toUUID !== toUUID + ), + } + : connection + ) + .filter((connection) => connection.toConnections.length > 0), + })), +})); + +export const useIsConnecting = create((set: any) => ({ + isConnecting: false, + setIsConnecting: (x: any) => set({ isConnecting: x }), +})); + +export const useStartSimulation = create((set: any) => ({ + startSimulation: false, + setStartSimulation: (x: any) => set({ startSimulation: x }), })); \ No newline at end of file diff --git a/app/src/store/useModuleStore.ts b/app/src/store/useModuleStore.ts index 6d26a8e..0eeb726 100644 --- a/app/src/store/useModuleStore.ts +++ b/app/src/store/useModuleStore.ts @@ -1,4 +1,3 @@ -// store/useModuleStore.ts import { create } from "zustand"; interface ModuleStore { @@ -12,3 +11,16 @@ const useModuleStore = create((set) => ({ })); export default useModuleStore; + +// New store for subModule +interface SubModuleStore { + subModule: string; + setSubModule: (subModule: string) => void; +} + +const useSubModuleStore = create((set) => ({ + subModule: "properties", // Initial subModule state + setSubModule: (subModule) => set({ subModule }), // Update subModule state +})); + +export { useSubModuleStore }; \ No newline at end of file diff --git a/app/src/store/usePlayButtonStore.ts b/app/src/store/usePlayButtonStore.ts index 5b2913c..e975a7c 100644 --- a/app/src/store/usePlayButtonStore.ts +++ b/app/src/store/usePlayButtonStore.ts @@ -1,11 +1,11 @@ -import { create } from "zustand"; - -type PlayButtonStore = { - isPlaying: boolean; // Updated state name to reflect the play/pause status more clearly - setIsPlaying: (value: boolean) => void; // Updated setter function name for clarity -}; - -export const usePlayButtonStore = create((set) => ({ - isPlaying: false, // Default state for play/pause - setIsPlaying: (value) => set({ isPlaying: value }), // Update isPlaying state -})); +import { create } from "zustand"; + +type PlayButtonStore = { + isPlaying: boolean; // Updated state name to reflect the play/pause status more clearly + setIsPlaying: (value: boolean) => void; // Updated setter function name for clarity +}; + +export const usePlayButtonStore = create((set) => ({ + isPlaying: false, // Default state for play/pause + setIsPlaying: (value) => set({ isPlaying: value }), // Update isPlaying state +})); diff --git a/app/src/store/useTemplateStore.ts b/app/src/store/useTemplateStore.ts index f8f3711..2adcd2f 100644 --- a/app/src/store/useTemplateStore.ts +++ b/app/src/store/useTemplateStore.ts @@ -1,39 +1,39 @@ -import { create } from "zustand"; - -// type Side = "top" | "bottom" | "left" | "right"; - -export interface Widget { - id: string; - type: string; - title: string; - panel: string; - data: any; -} - -export interface Template { - id: string; - name: string; - panelOrder: string[]; - widgets: Widget[]; - snapshot?: string | null; // Add an optional image property (base64) -} - -interface TemplateStore { - templates: Template[]; - addTemplate: (template: Template) => void; - removeTemplate: (id: string) => void; -} - -export const useTemplateStore = create((set) => ({ - templates: [], - addTemplate: (template) => - set((state) => ({ - templates: [...state.templates, template], - })), - removeTemplate: (id) => - set((state) => ({ - templates: state.templates.filter((t) => t.id !== id), - })), -})); - -export default useTemplateStore; +import { create } from "zustand"; + +// type Side = "top" | "bottom" | "left" | "right"; + +export interface Widget { + id: string; + type: string; + title: string; + panel: string; + data: any; +} + +export interface Template { + id: string; + name: string; + panelOrder: string[]; + widgets: Widget[]; + snapshot?: string | null; // Add an optional image property (base64) +} + +interface TemplateStore { + templates: Template[]; + addTemplate: (template: Template) => void; + removeTemplate: (id: string) => void; +} + +export const useTemplateStore = create((set) => ({ + templates: [], + addTemplate: (template) => + set((state) => ({ + templates: [...state.templates, template], + })), + removeTemplate: (id) => + set((state) => ({ + templates: state.templates.filter((t) => t.id !== id), + })), +})); + +export default useTemplateStore; diff --git a/app/src/store/useThemeStore.ts b/app/src/store/useThemeStore.ts index 944a77f..cab0940 100644 --- a/app/src/store/useThemeStore.ts +++ b/app/src/store/useThemeStore.ts @@ -1,11 +1,11 @@ -import { create } from "zustand"; - -interface ThemeState { - themeColor: string[]; // This should be an array of strings - setThemeColor: (colors: string[]) => void; // This function will accept an array of strings -} - -export const useThemeStore = create((set) => ({ - themeColor: ["#5c87df", "#EEEEFE", "#969BA7"], - setThemeColor: (colors) => set({ themeColor: colors }), -})); +import { create } from "zustand"; + +interface ThemeState { + themeColor: string[]; // This should be an array of strings + setThemeColor: (colors: string[]) => void; // This function will accept an array of strings +} + +export const useThemeStore = create((set) => ({ + themeColor: ["#5c87df", "#EEEEFE", "#969BA7"], + setThemeColor: (colors) => set({ themeColor: colors }), +})); diff --git a/app/src/store/useWidgetStore.ts b/app/src/store/useWidgetStore.ts index 013581b..115c6aa 100644 --- a/app/src/store/useWidgetStore.ts +++ b/app/src/store/useWidgetStore.ts @@ -1,49 +1,49 @@ -import { create } from "zustand"; - -export interface Widget { - id: string; - type: string; // Can be chart type or "progress" - panel: "top" | "bottom" | "left" | "right"; - title: string; - fontFamily?: string; - fontSize?: string; - fontWeight?: string; - data: { - // Chart data - labels?: string[]; - datasets?: Array<{ - data: number[]; - backgroundColor: string; - borderColor: string; - borderWidth: number; - }>; - // Progress card data - stocks?: Array<{ - key: string; - value: number; - description: string; - }>; - }; -} - -interface WidgetStore { - draggedAsset: Widget | null; // The currently dragged widget asset - widgets: Widget[]; // List of all widgets - selectedChartId: any; - setDraggedAsset: (asset: Widget | null) => void; // Setter for draggedAsset - addWidget: (widget: Widget) => void; // Add a new widget - setWidgets: (widgets: Widget[]) => void; // Replace the entire widgets array - setSelectedChartId: (widget: Widget | null) => void; // Set the selected chart/widget -} - -// Create the store with Zustand -export const useWidgetStore = create((set) => ({ - draggedAsset: null, - widgets: [], - selectedChartId: null, // Initialize as null, not as an array - setDraggedAsset: (asset) => set({ draggedAsset: asset }), - addWidget: (widget) => - set((state) => ({ widgets: [...state.widgets, widget] })), - setWidgets: (widgets) => set({ widgets }), - setSelectedChartId: (widget) => set({ selectedChartId: widget }), -})); +import { create } from "zustand"; + +export interface Widget { + id: string; + type: string; // Can be chart type or "progress" + panel: "top" | "bottom" | "left" | "right"; + title: string; + fontFamily?: string; + fontSize?: string; + fontWeight?: string; + data: { + // Chart data + labels?: string[]; + datasets?: Array<{ + data: number[]; + backgroundColor: string; + borderColor: string; + borderWidth: number; + }>; + // Progress card data + stocks?: Array<{ + key: string; + value: number; + description: string; + }>; + }; +} + +interface WidgetStore { + draggedAsset: Widget | null; // The currently dragged widget asset + widgets: Widget[]; // List of all widgets + selectedChartId: any; + setDraggedAsset: (asset: Widget | null) => void; // Setter for draggedAsset + addWidget: (widget: Widget) => void; // Add a new widget + setWidgets: (widgets: Widget[]) => void; // Replace the entire widgets array + setSelectedChartId: (widget: Widget | null) => void; // Set the selected chart/widget +} + +// Create the store with Zustand +export const useWidgetStore = create((set) => ({ + draggedAsset: null, + widgets: [], + selectedChartId: null, // Initialize as null, not as an array + setDraggedAsset: (asset) => set({ draggedAsset: asset }), + addWidget: (widget) => + set((state) => ({ widgets: [...state.widgets, widget] })), + setWidgets: (widgets) => set({ widgets }), + setSelectedChartId: (widget) => set({ selectedChartId: widget }), +})); diff --git a/app/src/store/useZoneStore.ts b/app/src/store/useZoneStore.ts index 5d7c4a4..4d623ec 100644 --- a/app/src/store/useZoneStore.ts +++ b/app/src/store/useZoneStore.ts @@ -1,41 +1,41 @@ -import { create } from "zustand"; - -type Side = "top" | "bottom" | "left" | "right"; - -interface Widget { - id: string; - type: string; - title: string; - panel: Side; - data: any; -} - -interface SelectedZoneState { - zoneName: string; - activeSides: Side[]; - panelOrder: Side[]; - lockedPanels: Side[]; - widgets: Widget[]; -} - -interface SelectedZoneStore { - selectedZone: SelectedZoneState; - setSelectedZone: (zone: Partial | ((prev: SelectedZoneState) => SelectedZoneState)) => void; -} - -export const useSelectedZoneStore = create((set) => ({ - selectedZone: { - zoneName: "Manufacturing unit", - activeSides: [], - panelOrder: [], - lockedPanels: [], - widgets: [], - }, - setSelectedZone: (zone) => - set((state) => ({ - selectedZone: - typeof zone === "function" - ? zone(state.selectedZone) // Handle functional updates - : { ...state.selectedZone, ...zone }, // Handle partial updates - })), +import { create } from "zustand"; + +type Side = "top" | "bottom" | "left" | "right"; + +interface Widget { + id: string; + type: string; + title: string; + panel: Side; + data: any; +} + +interface SelectedZoneState { + zoneName: string; + activeSides: Side[]; + panelOrder: Side[]; + lockedPanels: Side[]; + widgets: Widget[]; +} + +interface SelectedZoneStore { + selectedZone: SelectedZoneState; + setSelectedZone: (zone: Partial | ((prev: SelectedZoneState) => SelectedZoneState)) => void; +} + +export const useSelectedZoneStore = create((set) => ({ + selectedZone: { + zoneName: "Manufacturing unit", + activeSides: [], + panelOrder: [], + lockedPanels: [], + widgets: [], + }, + setSelectedZone: (zone) => + set((state) => ({ + selectedZone: + typeof zone === "function" + ? zone(state.selectedZone) // Handle functional updates + : { ...state.selectedZone, ...zone }, // Handle partial updates + })), })); \ No newline at end of file diff --git a/app/src/styles/abstracts/variables.scss b/app/src/styles/abstracts/variables.scss index 31a9cba..18822b6 100644 --- a/app/src/styles/abstracts/variables.scss +++ b/app/src/styles/abstracts/variables.scss @@ -1,119 +1,119 @@ -/* ======================================================================== - Global SCSS Variables - ======================================================================== - This file contains the global variables used across the project for - colors, typography, spacing, shadows, and other design tokens. - ======================================================================== */ - -@use "functions"; - -// ======================================================================== -// Font Imports -// ======================================================================== -@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Josefin+Sans:ital,wght@0,100..700;1,100..700&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap"); - -// ======================================================================== -// Colors -// ======================================================================== - -// Text colors -$text-color: #2b3344; // Primary text color -$text-disabled: #b7b7c6; // Disabled text color -$input-text-color: #595965; // Input field text color - -$text-color-dark: #f3f3fd; // Primary text color for dark mode -$text-disabled-dark: #6f6f7a; // Disabled text color for dark mode -$input-text-color-dark: #b5b5c8; // Input field text color for dark mode - -// Accent colors -$accent-color: #6f42c1; // Primary accent color -$accent-color-dark: #b392f0; // Primary accent color for dark mode -$highlight-accent-color: #e0dfff; // Highlighted accent for light mode -$highlight-accent-color-dark: #403e6a; // Highlighted accent for dark mode - -// Background colors -$background-color: #fcfdfd; // Main background color -$background-color-dark: #19191d; // Main background color for dark mode -$background-color-secondary: #e1e0ff80; // Secondary background color -$background-color-secondary-dark: #39394f99; // Secondary background color for dark mode -$background-color-gray: #f3f3f3; // Main background color -$background-color-gray-dark: #232323; // Main background color for dark mode - -// Border colors -$border-color: #e0dfff; // Default border color -$border-color-dark: #403e6a; // Border color for dark mode - -// Shadow color -$shadow-color: #3c3c431a; // Shadow base color for light and dark mode - -// Gradients -$acent-gradient-dark: linear-gradient( - 90deg, - #b392f0 0%, - #a676ff 100% -); // Dark mode accent gradient -$acent-gradient: linear-gradient( - 90deg, - #6f42c1 0%, - #925df3 100% -); // Light mode accent gradient - -// ======================================================================== -// Typography -// ======================================================================== - -// Font Family Variables -$font-inter: "Inter", sans-serif; // Inter font -$font-josefin-sans: "Josefin Sans", sans-serif; // Josefin Sans font -$font-poppins: "Poppins", sans-serif; // Poppins font -$font-roboto: "Roboto", sans-serif; // Roboto font - -// Font sizes (converted to rem using a utility function) -$tiny: 0.625rem; // Extra small text (10px) -$small: 0.75rem; // Small text (12px) -$regular: 0.8rem; // Default text size (14px) -$large: 1rem; // Large text size (16px) -$xlarge: 1.125rem; // Extra large text size (18px) -$xxlarge: 1.5rem; // Double extra large text size (24px) -$xxxlarge: 2rem; // Triple extra large text size (32px) - -// Font weights -$thin-weight: 300; // Regular font weight -$regular-weight: 400; // Regular font weight -$medium-weight: 500; // Medium font weight -$bold-weight: 600; // Bold font weight - -// ======================================================================== -// Z-Index Levels -// ======================================================================== - -// Z-index variables for layering -$z-index-drei-html: 1; // For drei's Html components -$z-index-default: 1; // For drei's Html components -$z-index-marketplace: 2; // For drei's Html components -$z-index-tools: 3; // For drei's Html components -$z-index-negative: -1; // For drei's Html components -$z-index-ui-base: 10; // Base UI elements -$z-index-ui-overlay: 20; // Overlay UI elements (e.g., modals, tooltips) -$z-index-ui-popup: 30; // Popups, dialogs, or higher-priority UI elements -$z-index-ui-highest: 50; // Highest priority elements (e.g., notifications, loading screens) - -// ======================================================================== -// Shadows -// ======================================================================== - -// Box shadow variables -$box-shadow-light: 0px 2px 4px $shadow-color; // Light shadow -$box-shadow-medium: 0px 4px 8px $shadow-color; // Medium shadow -$box-shadow-heavy: 0px 8px 16px $shadow-color; // Heavy shadow - -// ======================================================================== -// Border Radius -// ======================================================================== - -// Border radius variables -$border-radius-small: 4px; // Small rounded corners -$border-radius-medium: 6px; // Medium rounded corners -$border-radius-large: 12px; // Large rounded corners -$border-radius-circle: 50%; // Fully circular -$border-radius-extra-large: 20px; // Extra-large rounded corners +/* ======================================================================== + Global SCSS Variables + ======================================================================== + This file contains the global variables used across the project for + colors, typography, spacing, shadows, and other design tokens. + ======================================================================== */ + +@use "functions"; + +// ======================================================================== +// Font Imports +// ======================================================================== +@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Josefin+Sans:ital,wght@0,100..700;1,100..700&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap"); + +// ======================================================================== +// Colors +// ======================================================================== + +// Text colors +$text-color: #2b3344; // Primary text color +$text-disabled: #b7b7c6; // Disabled text color +$input-text-color: #595965; // Input field text color + +$text-color-dark: #f3f3fd; // Primary text color for dark mode +$text-disabled-dark: #6f6f7a; // Disabled text color for dark mode +$input-text-color-dark: #b5b5c8; // Input field text color for dark mode + +// Accent colors +$accent-color: #6f42c1; // Primary accent color +$accent-color-dark: #b392f0; // Primary accent color for dark mode +$highlight-accent-color: #e0dfff; // Highlighted accent for light mode +$highlight-accent-color-dark: #403e6a; // Highlighted accent for dark mode + +// Background colors +$background-color: #fcfdfd; // Main background color +$background-color-dark: #19191d; // Main background color for dark mode +$background-color-secondary: #e1e0ff80; // Secondary background color +$background-color-secondary-dark: #39394f99; // Secondary background color for dark mode +$background-color-gray: #f3f3f3; // Main background color +$background-color-gray-dark: #232323; // Main background color for dark mode + +// Border colors +$border-color: #e0dfff; // Default border color +$border-color-dark: #403e6a; // Border color for dark mode + +// Shadow color +$shadow-color: #3c3c431a; // Shadow base color for light and dark mode + +// Gradients +$acent-gradient-dark: linear-gradient( + 90deg, + #b392f0 0%, + #a676ff 100% +); // Dark mode accent gradient +$acent-gradient: linear-gradient( + 90deg, + #6f42c1 0%, + #925df3 100% +); // Light mode accent gradient + +// ======================================================================== +// Typography +// ======================================================================== + +// Font Family Variables +$font-inter: "Inter", sans-serif; // Inter font +$font-josefin-sans: "Josefin Sans", sans-serif; // Josefin Sans font +$font-poppins: "Poppins", sans-serif; // Poppins font +$font-roboto: "Roboto", sans-serif; // Roboto font + +// Font sizes (converted to rem using a utility function) +$tiny: 0.625rem; // Extra small text (10px) +$small: 0.75rem; // Small text (12px) +$regular: 0.8rem; // Default text size (14px) +$large: 1rem; // Large text size (16px) +$xlarge: 1.125rem; // Extra large text size (18px) +$xxlarge: 1.5rem; // Double extra large text size (24px) +$xxxlarge: 2rem; // Triple extra large text size (32px) + +// Font weights +$thin-weight: 300; // Regular font weight +$regular-weight: 400; // Regular font weight +$medium-weight: 500; // Medium font weight +$bold-weight: 600; // Bold font weight + +// ======================================================================== +// Z-Index Levels +// ======================================================================== + +// Z-index variables for layering +$z-index-drei-html: 1; // For drei's Html components +$z-index-default: 1; // For drei's Html components +$z-index-marketplace: 2; // For drei's Html components +$z-index-tools: 3; // For drei's Html components +$z-index-negative: -1; // For drei's Html components +$z-index-ui-base: 10; // Base UI elements +$z-index-ui-overlay: 20; // Overlay UI elements (e.g., modals, tooltips) +$z-index-ui-popup: 30; // Popups, dialogs, or higher-priority UI elements +$z-index-ui-highest: 50; // Highest priority elements (e.g., notifications, loading screens) + +// ======================================================================== +// Shadows +// ======================================================================== + +// Box shadow variables +$box-shadow-light: 0px 2px 4px $shadow-color; // Light shadow +$box-shadow-medium: 0px 4px 8px $shadow-color; // Medium shadow +$box-shadow-heavy: 0px 8px 16px $shadow-color; // Heavy shadow + +// ======================================================================== +// Border Radius +// ======================================================================== + +// Border radius variables +$border-radius-small: 4px; // Small rounded corners +$border-radius-medium: 6px; // Medium rounded corners +$border-radius-large: 12px; // Large rounded corners +$border-radius-circle: 50%; // Fully circular +$border-radius-extra-large: 20px; // Extra-large rounded corners diff --git a/app/src/styles/base/base.scss b/app/src/styles/base/base.scss index 925d44b..f7bf4b0 100644 --- a/app/src/styles/base/base.scss +++ b/app/src/styles/base/base.scss @@ -1,128 +1,128 @@ -@use "../abstracts/variables" as *; // abstracts/variables.scss - -// Light theme styles -[data-theme="light"] { - // Text and Input colors - --text-color: #{$text-color}; // Main text color for light theme - --text-disabled: #{$text-disabled}; // Disabled text color - --input-text-color: #{$input-text-color}; // Input field text color - - // Accent and Highlight colors - --primary-color: #{$background-color}; // Primary color for light theme - --accent-color: #{$accent-color}; // Primary accent color for light theme - --highlight-accent-color: #{$highlight-accent-color}; // Highlight color for light theme - --accent-gradient-color: #{$acent-gradient}; // Primary accent color for light theme - - // Background colors - --background-color: #{$background-color}; // Main background color - --background-color-secondary: #{$background-color-secondary}; // Secondary background color - --background-color-gray: #{$background-color-gray}; // Secondary background color - - // Border colors - --border-color: #{$border-color}; // Border color for light theme - - // Shadow variables - --shadow-main-light: #{$shadow-color}; // Main shadow color - --box-shadow-light: 0px 2px 4px var(--shadow-main-light); // Light shadow - --box-shadow-medium: 0px 4px 8px var(--shadow-main-light); // Medium shadow - --box-shadow-heavy: 0px 8px 16px var(--shadow-main-light); // Heavy shadow - - // Font families - --font-inter: #{$font-inter}; // Inter font family - --font-josefin-sans: #{$font-josefin-sans}; // Josefin Sans font family - --font-poppins: #{$font-poppins}; // Poppins font family - --font-roboto: #{$font-roboto}; // Roboto font family -} - -// Dark theme styles -[data-theme="dark"] { - // Text and Input colors - --text-color: #{$text-color-dark}; // Main text color for dark theme - --text-disabled: #{$text-disabled-dark}; // Disabled text color - --input-text-color: #{$input-text-color-dark}; // Input field text color - - // Accent and Highlight colors - --primary-color: #{$highlight-accent-color-dark}; - --accent-color: #{$accent-color-dark}; // Primary accent color for dark theme - --highlight-accent-color: #{$highlight-accent-color-dark}; // Highlight color for dark theme - --accent-gradient-color: #{$acent-gradient-dark}; // Primary accent color for light theme - - // Background colors - --background-color: #{$background-color-dark}; // Main background color - --background-color-secondary: #{$background-color-secondary-dark}; // Secondary background color - --background-color-gray: #{$background-color-gray-dark}; // Secondary background color - - // Border colors - --border-color: #{$border-color-dark}; // Border color for dark theme - - // Shadow variables - --shadow-main-dark: #{$shadow-color}; // Main shadow color - --box-shadow-light: 0px 2px 4px var(--shadow-main-dark); // Light shadow - --box-shadow-medium: 0px 4px 8px var(--shadow-main-dark); // Medium shadow - --box-shadow-heavy: 0px 8px 16px var(--shadow-main-dark); // Heavy shadow - - // Font families - --font-inter: #{$font-inter}; // Inter font family - --font-josefin-sans: #{$font-josefin-sans}; // Josefin Sans font family - --font-poppins: #{$font-poppins}; // Poppins font family - --font-roboto: #{$font-roboto}; // Roboto font family -} - -// Root container styles -#root { - height: 100vh; // Full viewport height - width: 100vw; // Full viewport width - overflow: hidden; // Prevent scrollbars -} - -// Root overlay styles -#root-over { - position: fixed; // Fix overlay to the viewport - top: 0; // Align to the top - left: 0; // Align to the left - z-index: 99; // Ensure high stacking order -} - -body { - - background: var(--background-color); - - /* Font Sizes */ - --font-size-tiny: #{$tiny}; // Extra small text - --font-size-small: #{$small}; // Small text - --font-size-regular: #{$regular}; // Default text size - --font-size-large: #{$large}; // Large text size - --font-size-xlarge: #{$xlarge}; // Extra large text size - --font-size-xxlarge: #{$xxlarge}; // Double extra large text size - --font-size-xxxlarge: #{$xxxlarge}; // Triple extra large text size - - /* Font Weights */ - --font-weight-regular: #{$regular-weight}; // Regular font weight - --font-weight-medium: #{$medium-weight}; // Medium font weight - --font-weight-bold: #{$bold-weight}; // Bold font weight -} - -/* Apply custom scrollbar styles globally */ -::-webkit-scrollbar { - width: 8px; /* Width of the scrollbar */ - height: 8px; /* Height for horizontal scrollbars */ -} - -::-webkit-scrollbar-track { - background: transparent; /* Background of the scrollbar track */ - border-radius: 4px; /* Rounded corners */ -} - -::-webkit-scrollbar-thumb { - background: var(--accent-color); /* Scrollbar handle color */ - border-radius: 4px; /* Rounded corners */ - border: 2px solid #f4f4f4; /* Padding around the scrollbar handle */ -} - -::-webkit-scrollbar-thumb:hover { - background: var(--accent-color); /* Handle color on hover */ -} - -::-webkit-scrollbar-corner { - background: transparent; /* Remove corner styling for scrollable containers */ -} +@use "../abstracts/variables" as *; // abstracts/variables.scss + +// Light theme styles +[data-theme="light"] { + // Text and Input colors + --text-color: #{$text-color}; // Main text color for light theme + --text-disabled: #{$text-disabled}; // Disabled text color + --input-text-color: #{$input-text-color}; // Input field text color + + // Accent and Highlight colors + --primary-color: #{$background-color}; // Primary color for light theme + --accent-color: #{$accent-color}; // Primary accent color for light theme + --highlight-accent-color: #{$highlight-accent-color}; // Highlight color for light theme + --accent-gradient-color: #{$acent-gradient}; // Primary accent color for light theme + + // Background colors + --background-color: #{$background-color}; // Main background color + --background-color-secondary: #{$background-color-secondary}; // Secondary background color + --background-color-gray: #{$background-color-gray}; // Secondary background color + + // Border colors + --border-color: #{$border-color}; // Border color for light theme + + // Shadow variables + --shadow-main-light: #{$shadow-color}; // Main shadow color + --box-shadow-light: 0px 2px 4px var(--shadow-main-light); // Light shadow + --box-shadow-medium: 0px 4px 8px var(--shadow-main-light); // Medium shadow + --box-shadow-heavy: 0px 8px 16px var(--shadow-main-light); // Heavy shadow + + // Font families + --font-inter: #{$font-inter}; // Inter font family + --font-josefin-sans: #{$font-josefin-sans}; // Josefin Sans font family + --font-poppins: #{$font-poppins}; // Poppins font family + --font-roboto: #{$font-roboto}; // Roboto font family +} + +// Dark theme styles +[data-theme="dark"] { + // Text and Input colors + --text-color: #{$text-color-dark}; // Main text color for dark theme + --text-disabled: #{$text-disabled-dark}; // Disabled text color + --input-text-color: #{$input-text-color-dark}; // Input field text color + + // Accent and Highlight colors + --primary-color: #{$highlight-accent-color-dark}; + --accent-color: #{$accent-color-dark}; // Primary accent color for dark theme + --highlight-accent-color: #{$highlight-accent-color-dark}; // Highlight color for dark theme + --accent-gradient-color: #{$acent-gradient-dark}; // Primary accent color for light theme + + // Background colors + --background-color: #{$background-color-dark}; // Main background color + --background-color-secondary: #{$background-color-secondary-dark}; // Secondary background color + --background-color-gray: #{$background-color-gray-dark}; // Secondary background color + + // Border colors + --border-color: #{$border-color-dark}; // Border color for dark theme + + // Shadow variables + --shadow-main-dark: #{$shadow-color}; // Main shadow color + --box-shadow-light: 0px 2px 4px var(--shadow-main-dark); // Light shadow + --box-shadow-medium: 0px 4px 8px var(--shadow-main-dark); // Medium shadow + --box-shadow-heavy: 0px 8px 16px var(--shadow-main-dark); // Heavy shadow + + // Font families + --font-inter: #{$font-inter}; // Inter font family + --font-josefin-sans: #{$font-josefin-sans}; // Josefin Sans font family + --font-poppins: #{$font-poppins}; // Poppins font family + --font-roboto: #{$font-roboto}; // Roboto font family +} + +// Root container styles +#root { + height: 100vh; // Full viewport height + width: 100vw; // Full viewport width + overflow: hidden; // Prevent scrollbars +} + +// Root overlay styles +#root-over { + position: fixed; // Fix overlay to the viewport + top: 0; // Align to the top + left: 0; // Align to the left + z-index: 99; // Ensure high stacking order +} + +body { + + background: var(--background-color); + + /* Font Sizes */ + --font-size-tiny: #{$tiny}; // Extra small text + --font-size-small: #{$small}; // Small text + --font-size-regular: #{$regular}; // Default text size + --font-size-large: #{$large}; // Large text size + --font-size-xlarge: #{$xlarge}; // Extra large text size + --font-size-xxlarge: #{$xxlarge}; // Double extra large text size + --font-size-xxxlarge: #{$xxxlarge}; // Triple extra large text size + + /* Font Weights */ + --font-weight-regular: #{$regular-weight}; // Regular font weight + --font-weight-medium: #{$medium-weight}; // Medium font weight + --font-weight-bold: #{$bold-weight}; // Bold font weight +} + +/* Apply custom scrollbar styles globally */ +::-webkit-scrollbar { + width: 8px; /* Width of the scrollbar */ + height: 8px; /* Height for horizontal scrollbars */ +} + +::-webkit-scrollbar-track { + background: transparent; /* Background of the scrollbar track */ + border-radius: 4px; /* Rounded corners */ +} + +::-webkit-scrollbar-thumb { + background: var(--accent-color); /* Scrollbar handle color */ + border-radius: 4px; /* Rounded corners */ + border: 2px solid #f4f4f4; /* Padding around the scrollbar handle */ +} + +::-webkit-scrollbar-thumb:hover { + background: var(--accent-color); /* Handle color on hover */ +} + +::-webkit-scrollbar-corner { + background: transparent; /* Remove corner styling for scrollable containers */ +} diff --git a/app/src/styles/base/reset.scss b/app/src/styles/base/reset.scss index 96ff717..b37f940 100644 --- a/app/src/styles/base/reset.scss +++ b/app/src/styles/base/reset.scss @@ -1,7 +1,7 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; - user-select: none; - font-size: var(--font-size-regular); -} +* { + margin: 0; + padding: 0; + box-sizing: border-box; + user-select: none; + font-size: var(--font-size-regular); +} diff --git a/app/src/styles/base/typography.scss b/app/src/styles/base/typography.scss index 9739ffb..7b5adca 100644 --- a/app/src/styles/base/typography.scss +++ b/app/src/styles/base/typography.scss @@ -1,8 +1,8 @@ -// Global Typography Styles -* { - // Setting default font family - font-family: var(--font-inter), sans-serif; - font-weight: var(--font-weight-regular); // Default font weight - font-size: var(--font-size-regular); // Default font size - color: var(--text-color); // Default text color -} +// Global Typography Styles +* { + // Setting default font family + font-family: var(--font-inter), sans-serif; + font-weight: var(--font-weight-regular); // Default font weight + font-size: var(--font-size-regular); // Default font size + color: var(--text-color); // Default text color +} diff --git a/app/src/styles/components/visualization/floating/energyConsumed.scss b/app/src/styles/components/visualization/floating/energyConsumed.scss index 36cb105..12ae8ad 100644 --- a/app/src/styles/components/visualization/floating/energyConsumed.scss +++ b/app/src/styles/components/visualization/floating/energyConsumed.scss @@ -1,110 +1,110 @@ -@use "../../../abstracts/variables" as *; -@use "../../../abstracts/mixins" as *; - -.floatingWidgets-wrapper { - display: flex; - flex-direction: column; - gap: 6px; - padding-top: 12px; - padding: 6px; - - .floating { - - min-height: 170px; - background: var(--background-color); - border: 1.23px solid var(--border-color); - box-shadow: 0px 4.91px 4.91px 0px #0000001c; - border-radius: $border-radius-medium; - padding: 18px; - } - - .working-state { - display: flex; - flex-direction: column; - gap: 6px; - - .state-working-top { - display: flex; - } - } -} - - - -.floatingWidgets-wrapper { - font-family: Arial, sans-serif; - color: #333; -} - -.floating.working-state { - width: 100%; - height: 283px; - background: #f5f5f5; - border-radius: 8px; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); - padding: 20px; - box-sizing: border-box; - -} - -.state-working-top { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 20px; - // flex-direction: column; -} - -.state { - font-size: 24px; - font-weight: bold; -} - -.working-status { - display: flex; - align-items: center; - gap: 8px; -} - -.working { - font-size: 20px; - color: #4CAF50; -} - -.dot { - display: inline-block; - width: 10px; - height: 10px; - background: #4CAF50; - border-radius: 50%; -} - -.img img { - width: 150px; - height: 100px; - border-radius: 4px; - object-fit: cover; -} - -.state-working-data { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 15px; -} - -.data-row { - display: flex; - justify-content: space-between; - align-items: center; - font-size: 16px; - padding: 4px 0; -} - -.data-key { - color: #666; -} - -.data-value { - font-weight: bold; - color: #333; +@use "../../../abstracts/variables" as *; +@use "../../../abstracts/mixins" as *; + +.floatingWidgets-wrapper { + display: flex; + flex-direction: column; + gap: 6px; + padding-top: 12px; + padding: 6px; + + .floating { + + min-height: 170px; + background: var(--background-color); + border: 1.23px solid var(--border-color); + box-shadow: 0px 4.91px 4.91px 0px #0000001c; + border-radius: $border-radius-medium; + padding: 18px; + } + + .working-state { + display: flex; + flex-direction: column; + gap: 6px; + + .state-working-top { + display: flex; + } + } +} + + + +.floatingWidgets-wrapper { + font-family: Arial, sans-serif; + color: #333; +} + +.floating.working-state { + width: 100%; + height: 283px; + background: #f5f5f5; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + padding: 20px; + box-sizing: border-box; + +} + +.state-working-top { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + // flex-direction: column; +} + +.state { + font-size: 24px; + font-weight: bold; +} + +.working-status { + display: flex; + align-items: center; + gap: 8px; +} + +.working { + font-size: 20px; + color: #4CAF50; +} + +.dot { + display: inline-block; + width: 10px; + height: 10px; + background: #4CAF50; + border-radius: 50%; +} + +.img img { + width: 150px; + height: 100px; + border-radius: 4px; + object-fit: cover; +} + +.state-working-data { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 15px; +} + +.data-row { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 16px; + padding: 4px 0; +} + +.data-key { + color: #666; +} + +.data-value { + font-weight: bold; + color: #333; } \ No newline at end of file diff --git a/app/src/types/declarations.d.ts b/app/src/types/declarations.d.ts index 00594f0..ccc8e5e 100644 --- a/app/src/types/declarations.d.ts +++ b/app/src/types/declarations.d.ts @@ -1,8 +1,8 @@ -declare module '*.png'; -declare module '*.svg'; -declare module '*.hdr'; -declare module '*.css'; -declare module '*.scss'; - -declare module '*.glb'; +declare module '*.png'; +declare module '*.svg'; +declare module '*.hdr'; +declare module '*.css'; +declare module '*.scss'; + +declare module '*.glb'; declare module '*.gltf'; \ No newline at end of file diff --git a/app/src/types/world/worldConstants.ts b/app/src/types/world/worldConstants.ts index ce5cacd..b14e799 100644 --- a/app/src/types/world/worldConstants.ts +++ b/app/src/types/world/worldConstants.ts @@ -1,384 +1,384 @@ -export type Controls = { - azimuthRotateSpeed: number; - polarRotateSpeed: number; - truckSpeed: number; - minDistance: number; - maxDistance: number; - maxPolarAngle: number; - leftMouse: number; - forwardSpeed: number; - backwardSpeed: number; - leftSpeed: number; - rightSpeed: number; -}; - -export type ThirdPersonControls = { - azimuthRotateSpeed: number; - polarRotateSpeed: number; - truckSpeed: number; - maxDistance: number; - maxPolarAngle: number; - minZoom: number; - maxZoom: number; - targetOffset: number; - cameraHeight: number; - leftMouse: number; - rightMouse: number; - wheelMouse: number; - middleMouse: number; -}; - -export type ControlsTransition = { - leftMouse: number; - rightMouse: number; - wheelMouse: number; - middleMouse: number; -}; - -export type TwoDimension = { - defaultPosition: [x: number, y: number, z: number]; - defaultTarget: [x: number, y: number, z: number]; - defaultAzimuth: number; - minDistance: number; - leftMouse: number; - rightMouse: number; -}; - -export type ThreeDimension = { - defaultPosition: [x: number, y: number, z: number]; - defaultTarget: [x: number, y: number, z: number]; - defaultRotation: [x: number, y: number, z: number]; - defaultAzimuth: number; - boundaryBottom: [x: number, y: number, z: number]; - boundaryTop: [x: number, y: number, z: number]; - minDistance: number; - leftMouse: number; - rightMouse: number; -}; - - -export type GridConfig = { - size: number; - divisions: number; - primaryColor: string; - secondaryColor: string; - - position2D: [x: number, y: number, z: number]; - position3D: [x: number, y: number, z: number]; -} - -export type PlaneConfig = { - position2D: [x: number, y: number, z: number]; - position3D: [x: number, y: number, z: number]; - rotation: number; - - width: number; - height: number; - color: string; -} - -export type ShadowConfig = { - shadowOffset: number, - - shadowmapSizewidth: number, - shadowmapSizeheight: number, - shadowcamerafar: number, - shadowcameranear: number, - shadowcameratop: number, - shadowcamerabottom: number, - shadowcameraleft: number, - shadowcameraright: number, - shadowbias: number, - shadownormalBias: number, - - shadowMaterialPosition: [x: number, y: number, z: number], - shadowMaterialRotation: [x: number, y: number, z: number], - - shadowMaterialOpacity: number, -} - -export type SkyConfig = { - defaultTurbidity: number; - maxTurbidity: number; - minTurbidity: number; - defaultRayleigh: number; - mieCoefficient: number; - mieDirectionalG: number; - skyDistance: number; -} - -export type AssetConfig = { - defaultScaleBeforeGsap: [number, number, number]; - defaultScaleAfterGsap: [number, number, number]; -} - -export type PointConfig = { - defaultInnerColor: string; - defaultOuterColor: string; - deleteColor: string; - boxScale: [number, number, number]; - - wallOuterColor: string; - floorOuterColor: string; - aisleOuterColor: string; - zoneOuterColor: string; - - snappingThreshold: number; -} - -export type LineConfig = { - tubularSegments: number; - radius: number; - radialSegments: number; - - wallName: string; - floorName: string; - aisleName: string; - zoneName: string; - referenceName: string; - - lineIntersectionPoints: number; - - defaultColor: string; - - wallColor: string; - floorColor: string; - aisleColor: string; - zoneColor: string; - helperColor: string; -} - -export type WallConfig = { - defaultColor: string; - height: number; - width: number; -} - -export type FloorConfig = { - defaultColor: string; - height: number; - - textureScale: number; -} - -export type RoofConfig = { - defaultColor: string; - height: number; -} - -export type AisleConfig = { - width: number; - height: number; - - defaultColor: number; -} - -export type ZoneConfig = { - defaultColor: string; - - color: string; -} - -export type ColumnConfig = { - defaultColor: string; -} - -export type OutlineConfig = { - assetSelectColor: number; - assetDeleteColor: number; -} - - - - -export const firstPersonControls: Controls = { - azimuthRotateSpeed: 0.3, // Speed of rotation around the azimuth axis - polarRotateSpeed: 0.3, // Speed of rotation around the polar axis - truckSpeed: 10, // Speed of truck movement - minDistance: 0, // Minimum distance from the target - maxDistance: 0, // Maximum distance from the target - maxPolarAngle: Math.PI, // Maximum polar angle - - leftMouse: 1, // Mouse button for rotation (ROTATE) - - forwardSpeed: 0.3, // Speed of forward movement - backwardSpeed: -0.3, // Speed of backward movement - leftSpeed: -0.3, // Speed of left movement - rightSpeed: 0.3, // Speed of right movement -}; - -export const thirdPersonControls: ThirdPersonControls = { - azimuthRotateSpeed: 1, // Speed of rotation around the azimuth axis - polarRotateSpeed: 1, // Speed of rotation around the polar axis - truckSpeed: 2, // Speed of truck movement - maxDistance: 100, // Maximum distance from the target - maxPolarAngle: Math.PI / 2 - 0.05, // Maximum polar angle - minZoom: 6, // Minimum zoom level - maxZoom: 21, // Maximum zoom level - targetOffset: 20, // Offset of the target from the camera - cameraHeight: 30, // Height of the camera - leftMouse: 2, // Mouse button for panning - rightMouse: 1, // Mouse button for rotation - wheelMouse: 8, // Mouse button for zooming - middleMouse: 8, // Mouse button for zooming -}; - -export const controlsTransition: ControlsTransition = { - leftMouse: 0, // Mouse button for no action - rightMouse: 0, // Mouse button for no action - wheelMouse: 0, // Mouse button for no action - middleMouse: 0, // Mouse button for no action -}; - -export const twoDimension: TwoDimension = { - defaultPosition: [0, 100, 0], // Default position of the camera - defaultTarget: [0, 0, 0], // Default target of the camera - defaultAzimuth: 0, // Default azimuth of the camera - minDistance: 25, // Minimum distance from the target - leftMouse: 2, // Mouse button for panning - rightMouse: 0, // Mouse button for no action -}; - -export const threeDimension: ThreeDimension = { - defaultPosition: [0, 40, 30], // Default position of the camera - defaultTarget: [0, 0, 0], // Default target of the camera - defaultRotation: [0, 0, 0], // Default rotation of the camera - defaultAzimuth: 0, // Default azimuth of the camera - boundaryBottom: [-150, 0, -150], // Bottom boundary of the camera movement - boundaryTop: [150, 100, 150], // Top boundary of the camera movement - minDistance: 1, // Minimum distance from the target - leftMouse: 2, // Mouse button for panning - rightMouse: 1, // Mouse button for rotation -}; - -export const camPositionUpdateInterval: number = 200; // Interval for updating the camera position - -export const gridConfig: GridConfig = { - size: 300, // Size of the grid - divisions: 75, // Number of divisions in the grid - primaryColor: "#d5d5d5", // Primary color of the grid - secondaryColor: "#e3e3e3", // Secondary color of the grid - - position2D: [0, 0.1, 0], // Position of the grid in 2D view - position3D: [0, -0.5, 0], // Position of the grid in 3D view -} - -export const planeConfig: PlaneConfig = { - position2D: [0, -0.5, 0], // Position of the plane - position3D: [0, -0.65, 0], // Position of the plane - rotation: -Math.PI / 2, // Rotation of the plane - - width: 300, // Width of the plane - height: 300, // Height of the plane - color: "white" // Color of the plane -} - -export const shadowConfig: ShadowConfig = { - shadowOffset: 50, // Offset of the shadow - - shadowmapSizewidth: 1024, // Width of the shadow map - shadowmapSizeheight: 1024, // Height of the shadow map - // shadowmapSizewidth: 8192, // Width of the shadow map - // shadowmapSizeheight: 8192, // Height of the shadow map - shadowcamerafar: 70, // Far plane of the shadow camera - shadowcameranear: 0.1, // Near plane of the shadow camera - shadowcameratop: 30, // Top plane of the shadow camera - shadowcamerabottom: -30, // Bottom plane of the shadow camera - shadowcameraleft: -30, // Left plane of the shadow camera - shadowcameraright: 30, // Right plane of the shadow camera - shadowbias: -0.001, // Bias of the shadow - shadownormalBias: 0.02, // Normal bias of the shadow - - shadowMaterialPosition: [0, 0.01, 0], // Position of the shadow material - shadowMaterialRotation: [-Math.PI / 2, 0, 0], // Rotation of the shadow material - - shadowMaterialOpacity: 0.1 // Opacity of the shadow material -} - -export const skyConfig: SkyConfig = { - defaultTurbidity: 10.0, // Default turbidity of the sky - maxTurbidity: 20.0, // Maximum turbidity of the sky - minTurbidity: 0.0, // Minimum turbidity of the sky - defaultRayleigh: 1.9, // Default Rayleigh scattering coefficient - mieCoefficient: 0.1, // Mie scattering coefficient - mieDirectionalG: 1.0, // Mie directional G - skyDistance: 2000 // Distance of the sky -} - -export const assetConfig: AssetConfig = { - defaultScaleBeforeGsap: [0.1, 0.1, 0.1], // Default scale of the assets - defaultScaleAfterGsap: [1, 1, 1] // Default scale of the assets -} - -export const pointConfig: PointConfig = { - defaultInnerColor: "#ffffff", // Default inner color of the points - defaultOuterColor: "#ffffff", // Default outer color of the points - deleteColor: "#ff0000", // Color of the points when deleting - boxScale: [0.5, 0.5, 0.5], // Scale of the points - - wallOuterColor: "#C7C7C7", // Outer color of the wall points - floorOuterColor: "#808080", // Outer color of the floor points - aisleOuterColor: "#FBBC05", // Outer color of the aisle points - zoneOuterColor: "#007BFF", // Outer color of the zone points - - snappingThreshold: 1, // Threshold for snapping -} - -export const lineConfig: LineConfig = { - tubularSegments: 64, // Number of tubular segments - radius: 0.15, // Radius of the lines - radialSegments: 8, // Number of radial segments - - wallName: "WallLine", // Name of the wall lines - floorName: "FloorLine", // Name of the floor lines - aisleName: "AisleLine", // Name of the aisle lines - zoneName: "ZoneLine", // Name of the zone lines - referenceName: "ReferenceLine", // Name of the reference lines - - lineIntersectionPoints: 300, // Number of intersection points - - defaultColor: "#000000", // Default color of the lines - - wallColor: "#C7C7C7", // Color of the wall lines - floorColor: "#808080", // Color of the floor lines - aisleColor: "#FBBC05", // Color of the aisle lines - zoneColor: "#007BFF", // Color of the zone lines - helperColor: "#C164FF" // Color of the helper lines -} - -export const wallConfig: WallConfig = { - defaultColor: "white", // Default color of the walls - height: 7, // Height of the walls - width: 0.05, // Width of the walls -} - -export const floorConfig: FloorConfig = { - defaultColor: "grey", // Default color of the floors - height: 0.1, // Height of the floors - textureScale: 0.1, // Scale of the floor texture -} - -export const roofConfig: RoofConfig = { - defaultColor: "grey", // Default color of the roofs - height: 0.1 // Height of the roofs -} - -export const aisleConfig: AisleConfig = { - width: 0.1, // Width of the aisles - height: 0.01, // Height of the aisles - defaultColor: 0xffff00 // Default color of the aisles -} - -export const zoneConfig: ZoneConfig = { - defaultColor: "black", // Default color of the zones - color: "blue" // Color of the zones -} - -export const columnConfig: ColumnConfig = { - defaultColor: "White", // Default color of the columns -} - -export const outlineConfig: OutlineConfig = { - assetSelectColor: 0x0054fE, // Color of the selected assets - assetDeleteColor: 0xFF0000 // Color of the deleted assets +export type Controls = { + azimuthRotateSpeed: number; + polarRotateSpeed: number; + truckSpeed: number; + minDistance: number; + maxDistance: number; + maxPolarAngle: number; + leftMouse: number; + forwardSpeed: number; + backwardSpeed: number; + leftSpeed: number; + rightSpeed: number; +}; + +export type ThirdPersonControls = { + azimuthRotateSpeed: number; + polarRotateSpeed: number; + truckSpeed: number; + maxDistance: number; + maxPolarAngle: number; + minZoom: number; + maxZoom: number; + targetOffset: number; + cameraHeight: number; + leftMouse: number; + rightMouse: number; + wheelMouse: number; + middleMouse: number; +}; + +export type ControlsTransition = { + leftMouse: number; + rightMouse: number; + wheelMouse: number; + middleMouse: number; +}; + +export type TwoDimension = { + defaultPosition: [x: number, y: number, z: number]; + defaultTarget: [x: number, y: number, z: number]; + defaultAzimuth: number; + minDistance: number; + leftMouse: number; + rightMouse: number; +}; + +export type ThreeDimension = { + defaultPosition: [x: number, y: number, z: number]; + defaultTarget: [x: number, y: number, z: number]; + defaultRotation: [x: number, y: number, z: number]; + defaultAzimuth: number; + boundaryBottom: [x: number, y: number, z: number]; + boundaryTop: [x: number, y: number, z: number]; + minDistance: number; + leftMouse: number; + rightMouse: number; +}; + + +export type GridConfig = { + size: number; + divisions: number; + primaryColor: string; + secondaryColor: string; + + position2D: [x: number, y: number, z: number]; + position3D: [x: number, y: number, z: number]; +} + +export type PlaneConfig = { + position2D: [x: number, y: number, z: number]; + position3D: [x: number, y: number, z: number]; + rotation: number; + + width: number; + height: number; + color: string; +} + +export type ShadowConfig = { + shadowOffset: number, + + shadowmapSizewidth: number, + shadowmapSizeheight: number, + shadowcamerafar: number, + shadowcameranear: number, + shadowcameratop: number, + shadowcamerabottom: number, + shadowcameraleft: number, + shadowcameraright: number, + shadowbias: number, + shadownormalBias: number, + + shadowMaterialPosition: [x: number, y: number, z: number], + shadowMaterialRotation: [x: number, y: number, z: number], + + shadowMaterialOpacity: number, +} + +export type SkyConfig = { + defaultTurbidity: number; + maxTurbidity: number; + minTurbidity: number; + defaultRayleigh: number; + mieCoefficient: number; + mieDirectionalG: number; + skyDistance: number; +} + +export type AssetConfig = { + defaultScaleBeforeGsap: [number, number, number]; + defaultScaleAfterGsap: [number, number, number]; +} + +export type PointConfig = { + defaultInnerColor: string; + defaultOuterColor: string; + deleteColor: string; + boxScale: [number, number, number]; + + wallOuterColor: string; + floorOuterColor: string; + aisleOuterColor: string; + zoneOuterColor: string; + + snappingThreshold: number; +} + +export type LineConfig = { + tubularSegments: number; + radius: number; + radialSegments: number; + + wallName: string; + floorName: string; + aisleName: string; + zoneName: string; + referenceName: string; + + lineIntersectionPoints: number; + + defaultColor: string; + + wallColor: string; + floorColor: string; + aisleColor: string; + zoneColor: string; + helperColor: string; +} + +export type WallConfig = { + defaultColor: string; + height: number; + width: number; +} + +export type FloorConfig = { + defaultColor: string; + height: number; + + textureScale: number; +} + +export type RoofConfig = { + defaultColor: string; + height: number; +} + +export type AisleConfig = { + width: number; + height: number; + + defaultColor: number; +} + +export type ZoneConfig = { + defaultColor: string; + + color: string; +} + +export type ColumnConfig = { + defaultColor: string; +} + +export type OutlineConfig = { + assetSelectColor: number; + assetDeleteColor: number; +} + + + + +export const firstPersonControls: Controls = { + azimuthRotateSpeed: 0.3, // Speed of rotation around the azimuth axis + polarRotateSpeed: 0.3, // Speed of rotation around the polar axis + truckSpeed: 10, // Speed of truck movement + minDistance: 0, // Minimum distance from the target + maxDistance: 0, // Maximum distance from the target + maxPolarAngle: Math.PI, // Maximum polar angle + + leftMouse: 1, // Mouse button for rotation (ROTATE) + + forwardSpeed: 0.3, // Speed of forward movement + backwardSpeed: -0.3, // Speed of backward movement + leftSpeed: -0.3, // Speed of left movement + rightSpeed: 0.3, // Speed of right movement +}; + +export const thirdPersonControls: ThirdPersonControls = { + azimuthRotateSpeed: 1, // Speed of rotation around the azimuth axis + polarRotateSpeed: 1, // Speed of rotation around the polar axis + truckSpeed: 2, // Speed of truck movement + maxDistance: 100, // Maximum distance from the target + maxPolarAngle: Math.PI / 2 - 0.05, // Maximum polar angle + minZoom: 6, // Minimum zoom level + maxZoom: 21, // Maximum zoom level + targetOffset: 20, // Offset of the target from the camera + cameraHeight: 30, // Height of the camera + leftMouse: 2, // Mouse button for panning + rightMouse: 1, // Mouse button for rotation + wheelMouse: 8, // Mouse button for zooming + middleMouse: 8, // Mouse button for zooming +}; + +export const controlsTransition: ControlsTransition = { + leftMouse: 0, // Mouse button for no action + rightMouse: 0, // Mouse button for no action + wheelMouse: 0, // Mouse button for no action + middleMouse: 0, // Mouse button for no action +}; + +export const twoDimension: TwoDimension = { + defaultPosition: [0, 100, 0], // Default position of the camera + defaultTarget: [0, 0, 0], // Default target of the camera + defaultAzimuth: 0, // Default azimuth of the camera + minDistance: 25, // Minimum distance from the target + leftMouse: 2, // Mouse button for panning + rightMouse: 0, // Mouse button for no action +}; + +export const threeDimension: ThreeDimension = { + defaultPosition: [0, 40, 30], // Default position of the camera + defaultTarget: [0, 0, 0], // Default target of the camera + defaultRotation: [0, 0, 0], // Default rotation of the camera + defaultAzimuth: 0, // Default azimuth of the camera + boundaryBottom: [-150, 0, -150], // Bottom boundary of the camera movement + boundaryTop: [150, 100, 150], // Top boundary of the camera movement + minDistance: 1, // Minimum distance from the target + leftMouse: 2, // Mouse button for panning + rightMouse: 1, // Mouse button for rotation +}; + +export const camPositionUpdateInterval: number = 200; // Interval for updating the camera position + +export const gridConfig: GridConfig = { + size: 300, // Size of the grid + divisions: 75, // Number of divisions in the grid + primaryColor: "#d5d5d5", // Primary color of the grid + secondaryColor: "#e3e3e3", // Secondary color of the grid + + position2D: [0, 0.1, 0], // Position of the grid in 2D view + position3D: [0, -0.5, 0], // Position of the grid in 3D view +} + +export const planeConfig: PlaneConfig = { + position2D: [0, -0.5, 0], // Position of the plane + position3D: [0, -0.65, 0], // Position of the plane + rotation: -Math.PI / 2, // Rotation of the plane + + width: 300, // Width of the plane + height: 300, // Height of the plane + color: "#f3f3f3" // Color of the plane +} + +export const shadowConfig: ShadowConfig = { + shadowOffset: 50, // Offset of the shadow + + shadowmapSizewidth: 1024, // Width of the shadow map + shadowmapSizeheight: 1024, // Height of the shadow map + // shadowmapSizewidth: 8192, // Width of the shadow map + // shadowmapSizeheight: 8192, // Height of the shadow map + shadowcamerafar: 70, // Far plane of the shadow camera + shadowcameranear: 0.1, // Near plane of the shadow camera + shadowcameratop: 30, // Top plane of the shadow camera + shadowcamerabottom: -30, // Bottom plane of the shadow camera + shadowcameraleft: -30, // Left plane of the shadow camera + shadowcameraright: 30, // Right plane of the shadow camera + shadowbias: -0.001, // Bias of the shadow + shadownormalBias: 0.02, // Normal bias of the shadow + + shadowMaterialPosition: [0, 0.01, 0], // Position of the shadow material + shadowMaterialRotation: [-Math.PI / 2, 0, 0], // Rotation of the shadow material + + shadowMaterialOpacity: 0.1 // Opacity of the shadow material +} + +export const skyConfig: SkyConfig = { + defaultTurbidity: 10.0, // Default turbidity of the sky + maxTurbidity: 20.0, // Maximum turbidity of the sky + minTurbidity: 0.0, // Minimum turbidity of the sky + defaultRayleigh: 1.9, // Default Rayleigh scattering coefficient + mieCoefficient: 0.1, // Mie scattering coefficient + mieDirectionalG: 1.0, // Mie directional G + skyDistance: 2000 // Distance of the sky +} + +export const assetConfig: AssetConfig = { + defaultScaleBeforeGsap: [0.1, 0.1, 0.1], // Default scale of the assets + defaultScaleAfterGsap: [1, 1, 1] // Default scale of the assets +} + +export const pointConfig: PointConfig = { + defaultInnerColor: "#ffffff", // Default inner color of the points + defaultOuterColor: "#ffffff", // Default outer color of the points + deleteColor: "#ff0000", // Color of the points when deleting + boxScale: [0.5, 0.5, 0.5], // Scale of the points + + wallOuterColor: "#C7C7C7", // Outer color of the wall points + floorOuterColor: "#808080", // Outer color of the floor points + aisleOuterColor: "#FBBC05", // Outer color of the aisle points + zoneOuterColor: "#007BFF", // Outer color of the zone points + + snappingThreshold: 1, // Threshold for snapping +} + +export const lineConfig: LineConfig = { + tubularSegments: 64, // Number of tubular segments + radius: 0.15, // Radius of the lines + radialSegments: 8, // Number of radial segments + + wallName: "WallLine", // Name of the wall lines + floorName: "FloorLine", // Name of the floor lines + aisleName: "AisleLine", // Name of the aisle lines + zoneName: "ZoneLine", // Name of the zone lines + referenceName: "ReferenceLine", // Name of the reference lines + + lineIntersectionPoints: 300, // Number of intersection points + + defaultColor: "#000000", // Default color of the lines + + wallColor: "#C7C7C7", // Color of the wall lines + floorColor: "#808080", // Color of the floor lines + aisleColor: "#FBBC05", // Color of the aisle lines + zoneColor: "#007BFF", // Color of the zone lines + helperColor: "#C164FF" // Color of the helper lines +} + +export const wallConfig: WallConfig = { + defaultColor: "white", // Default color of the walls + height: 7, // Height of the walls + width: 0.05, // Width of the walls +} + +export const floorConfig: FloorConfig = { + defaultColor: "grey", // Default color of the floors + height: 0.1, // Height of the floors + textureScale: 0.1, // Scale of the floor texture +} + +export const roofConfig: RoofConfig = { + defaultColor: "grey", // Default color of the roofs + height: 0.1 // Height of the roofs +} + +export const aisleConfig: AisleConfig = { + width: 0.1, // Width of the aisles + height: 0.01, // Height of the aisles + defaultColor: 0xffff00 // Default color of the aisles +} + +export const zoneConfig: ZoneConfig = { + defaultColor: "black", // Default color of the zones + color: "blue" // Color of the zones +} + +export const columnConfig: ColumnConfig = { + defaultColor: "White", // Default color of the columns +} + +export const outlineConfig: OutlineConfig = { + assetSelectColor: 0x0054fE, // Color of the selected assets + assetDeleteColor: 0xFF0000 // Color of the deleted assets } \ No newline at end of file diff --git a/app/src/types/world/worldTypes.d.ts b/app/src/types/world/worldTypes.d.ts index 9d3fad0..c1e7128 100644 --- a/app/src/types/world/worldTypes.d.ts +++ b/app/src/types/world/worldTypes.d.ts @@ -1,307 +1,287 @@ -// Importing core classes and types from THREE.js and @react-three/fiber -import * as THREE from "three"; -import { TransformControls } from 'three/examples/jsm/controls/TransformControls'; -import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; -import { DragControls } from 'three/examples/jsm/controls/DragControls'; -import { IntersectionEvent } from '@react-three/fiber/dist/declarations/src/core/events'; -import { ThreeEvent } from "@react-three/fiber/dist/declarations/src/core/events"; -import { RootState } from "@react-three/fiber"; -import { CSM } from "three/examples/jsm/csm/CSM"; -import { CSMHelper } from 'three/examples/jsm/csm/CSMHelper'; -import { CameraControls } from "@react-three/drei"; - -/** Core THREE.js and React-Fiber Event Types **/ - -// Event type specific to pointer events in @react-three/fiber -export type ThreeEvent = ThreeEvent; - - -/** Vector and Reference Types **/ - -// 2D Vector type from THREE.js -export type Vector2 = THREE.Vector2; - -// React ref for a mutable 2D vector, useful for tracking changes over time -export type RefVector2 = React.MutableRefObject; - -// 3D Vector type from THREE.js -export type Vector3 = THREE.Vector3; - -// Mutable reference for 3D vectors, allowing for dynamic scene changes -export type RefVector3 = React.MutableRefObject; - -// Quaternion type for rotations, using the base structure from THREE.js -export type QuaternionType = THREE.QuaternionLike; - - -/** Basic Object Types for Scene Management **/ - -// THREE.js mesh object -export type Mesh = THREE.Mesh; - -// Color type allowing various formats (hex, RGB, string, etc.) -export type Color = THREE.Color | string | number; - -// Shape type for defining custom geometries -export type Shape = THREE.Shape; - -// Event type for intersections within the scene -export type IntersectionEvent = THREE.Intersection; - -// Array type for intersections with objects in the scene -export type IntersectsType = THREE.Intersection>[]; - -// Event type for mesh interactions -export type MeshEvent = IntersectionEvent; - -// Event type for drag interactions -export type DragEvent = DragEvent; - -// Generic type for user data attached to objects -export type UserData = any; - - -/** React Mutable References for Scene Objects **/ - -// Mutable reference to the scene, used in React-based projects -export type RefScene = React.MutableRefObject; - -// THREE.js group type for grouping objects -export type Group = THREE.Group; - -// Mutable reference for groups, supporting updates in React components -export type RefGroup = React.MutableRefObject; - -// Reference type for meshes, allowing null or undefined values -export type RefMesh = React.MutableRefObject; - -// Mutable reference to camera controls -export type RefControls = React.MutableRefObject; - -// Control types for transformation controls in the scene -export type TransformControl = TransformControl; -export type RefTransformControl = React.MutableRefObject; - -// Array of mesh references for tracking multiple meshes -export type RefMeshArray = React.MutableRefObject; - -// Array of 3D vectors, useful for handling points or positions -export type Vector3Array = THREE.Vector3[]; - -// Drag control type, either a valid DragControls instance or null -export type DragControl = DragControls | null; -export type RefDragControl = React.MutableRefObject; - - -/** Primitive Types with Mutable References **/ - -export type String = string; -export type RefStringArray = React.MutableRefObject; -export type RefString = React.MutableRefObject; - -export type Boolean = boolean; -export type RefBoolean = React.MutableRefObject; - -export type Number = number; -export type NumberArray = number[]; - -// Reference for the THREE.js Raycaster, useful in handling ray intersections -export type RefRaycaster = React.MutableRefObject; - -// Camera reference, supporting both perspective and basic cameras -export type RefCamera = React.MutableRefObject; - - -/** Three.js Root State Management **/ - -// Root state of the @react-three/fiber instance, providing context of the scene -export type ThreeState = RootState; - - -/** Point and Line Types for Spatial Geometry **/ - -// Defines a point in 3D space with metadata for unique identification -export type Point = [THREE.Vector3, string, number, string]; - -// Defines a line as two connected points, commonly used in scene building -export type Line = [Point, Point]; - -// Reference for a line, allowing dynamic updates -export type RefLine = React.MutableRefObject; - -// Collection of lines for structured geometry -export type Lines = Array; - - -/** Wall and Room Types for 3D Space Management **/ - -// Defines a wall with its geometry, position, rotation, material, and layer information -export type Wall = [THREE.ExtrudeGeometry, [number, number, number], [number, number, number], string, number]; - -// Collection of walls, useful in scene construction -export type Walls = Array; - -// Reference type for walls, allowing dynamic updates in React -export type RefWalls = React.MutableRefObject; - -// Room type, containing coordinates and layer metadata for spatial management -export type Rooms = Array<{ coordinates: Array<{ position: THREE.Vector3, uuid: string }>, layer: number }>; - -// Reference for room objects, enabling updates within React components -export type RefRooms = React.MutableRefObject, layer: number }>>; - -// Reference for lines, supporting React-based state changes -export type RefLines = React.MutableRefObject; - - -/** Floor Line Types for Layered Structures **/ - -// Floor line type for single lines on the floor level -export type OnlyFloorLine = Array; - -// Reference for floor lines, allowing manipulation in React -export type RefOnlyFloorLine = React.MutableRefObject; - -// Collection of lines across multiple floors, for multi-level structures -export type OnlyFloorLines = Array; - -// Reference for multi-level floor lines, allowing structured updates -export type RefOnlyFloorLines = React.MutableRefObject; - - -/** GeoJSON Line Integration **/ - -// Structure for representing GeoJSON lines, integrating external data sources -export type GeoJsonLine = { - line: any; - uuids: [string, string]; - layer: number; - type: string; -}; - - -/** State Management Types for React Components **/ - -// Dispatch types for number and boolean states, commonly used in React hooks -export type NumberIncrementState = React.Dispatch>; -export type BooleanState = React.Dispatch>; - -// Mutable reference for TubeGeometry, allowing dynamic geometry updates -export type RefTubeGeometry = React.MutableRefObject; - - -/** Floor Item Configuration **/ - -// Type for individual items placed on the floor, with positioning and rotation metadata -export type FloorItemType = { - modeluuid: string; - modelname: string; - position: [number, number, number]; - rotation: { x: number; y: number; z: number }; - modelfileID?: string; - isLocked: boolean; - isVisible: boolean; -}; - -// Array of floor items for managing multiple objects on the floor -export type FloorItems = Array; - -// Dispatch type for setting floor item state in React -export type setFloorItemSetState = React.Dispatch>; - - -/** Asset Configuration for Loading and Positioning **/ - -// Configuration for assets, allowing model URLs, scaling, positioning, and types -interface AssetConfiguration { - modelUrl: string; - scale?: [number, number, number]; - csgscale?: [number, number, number]; - csgposition?: [number, number, number]; - positionY?: (intersectionPoint: { point: THREE.Vector3 }) => number; - type?: "Fixed-Move" | "Free-Move"; -} - -// Collection of asset configurations, keyed by unique identifiers -export type AssetConfigurations = { - [key: string]: AssetConfiguration; -}; - - -/** Wall Item Configuration **/ - -// Configuration for wall items, including model, scale, position, and rotation -interface WallItem { - type: "Fixed-Move" | "Free-Move" | undefined; - model?: THREE.Group; - modeluuid?: string - modelname?: string; - scale?: [number, number, number]; - csgscale?: [number, number, number]; - csgposition?: [number, number, number]; - position?: [number, number, number]; - quaternion?: Types.QuaternionType; -} - -// Collection of wall items, allowing for multiple items in a scene -export type wallItems = Array; - -// Dispatch for setting wall item state in React -export type setWallItemSetState = React.Dispatch>; - -// Dispatch for setting vector3 state in React -export type setVector3State = React.Dispatch>; - -// Dispatch for setting euler state in React -export type setEulerState = React.Dispatch>; - -// Reference type for wall items, allowing direct access to the mutable array -export type RefWallItems = React.MutableRefObject; - - -/** Wall and Item Selection State Management **/ - -// State management for selecting, removing, and indexing wall items -export type setRemoveLayerSetState = (layer: number | null) => void; -export type setSelectedWallItemSetState = (item: THREE.Object3D | null) => void; -export type setSelectedFloorItemSetState = (item: THREE.Object3D | null) => void; -export type setSelectedItemsIndexSetState = (index: number | null) => void; - -export type RefCSM = React.MutableRefObject; -export type RefCSMHelper = React.MutableRefObject; - - -interface Path { - modeluuid: string; - points: { - uuid: string; - position: [number, number, number]; - rotation: [number, number, number]; - events: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; - triggers: { uuid: string; type: string; isUsed: boolean }[] | []; - }[]; - pathPosition: [number, number, number]; - pathRotation: [number, number, number]; - speed: number; -} - -interface SimulationPathsStore { - simulationPaths: Path[]; - setSimulationPaths: (paths: Path[]) => void; -} - -interface PathConnection { - fromPathUUID: string; - fromUUID: string; - toConnections: { - toPathUUID: string; - toUUID: string; - }[]; -} - -interface ConnectionStore { - connections: PathConnection[]; - setConnections: (connections: PathConnection[]) => void; - addConnection: (newConnection: PathConnection) => void; - removeConnection: (fromUUID: string, toUUID: string) => void; +// Importing core classes and types from THREE.js and @react-three/fiber +import * as THREE from "three"; +import { TransformControls } from 'three/examples/jsm/controls/TransformControls'; +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; +import { DragControls } from 'three/examples/jsm/controls/DragControls'; +import { IntersectionEvent } from '@react-three/fiber/dist/declarations/src/core/events'; +import { ThreeEvent } from "@react-three/fiber/dist/declarations/src/core/events"; +import { RootState } from "@react-three/fiber"; +import { CSM } from "three/examples/jsm/csm/CSM"; +import { CSMHelper } from 'three/examples/jsm/csm/CSMHelper'; +import { CameraControls } from "@react-three/drei"; + +/** Core THREE.js and React-Fiber Event Types **/ + +// Event type specific to pointer events in @react-three/fiber +export type ThreeEvent = ThreeEvent; + + +/** Vector and Reference Types **/ + +// 2D Vector type from THREE.js +export type Vector2 = THREE.Vector2; + +// React ref for a mutable 2D vector, useful for tracking changes over time +export type RefVector2 = React.MutableRefObject; + +// 3D Vector type from THREE.js +export type Vector3 = THREE.Vector3; + +// Mutable reference for 3D vectors, allowing for dynamic scene changes +export type RefVector3 = React.MutableRefObject; + +// Quaternion type for rotations, using the base structure from THREE.js +export type QuaternionType = THREE.QuaternionLike; + + +/** Basic Object Types for Scene Management **/ + +// THREE.js mesh object +export type Mesh = THREE.Mesh; + +// Color type allowing various formats (hex, RGB, string, etc.) +export type Color = THREE.Color | string | number; + +// Shape type for defining custom geometries +export type Shape = THREE.Shape; + +// Event type for intersections within the scene +export type IntersectionEvent = THREE.Intersection; + +// Array type for intersections with objects in the scene +export type IntersectsType = THREE.Intersection>[]; + +// Event type for mesh interactions +export type MeshEvent = IntersectionEvent; + +// Event type for drag interactions +export type DragEvent = DragEvent; + +// Generic type for user data attached to objects +export type UserData = any; + + +/** React Mutable References for Scene Objects **/ + +// Mutable reference to the scene, used in React-based projects +export type RefScene = React.MutableRefObject; + +// THREE.js group type for grouping objects +export type Group = THREE.Group; + +// Mutable reference for groups, supporting updates in React components +export type RefGroup = React.MutableRefObject; + +// Reference type for meshes, allowing null or undefined values +export type RefMesh = React.MutableRefObject; + +// Mutable reference to camera controls +export type RefControls = React.MutableRefObject; + +// Control types for transformation controls in the scene +export type TransformControl = TransformControl; +export type RefTransformControl = React.MutableRefObject; + +// Array of mesh references for tracking multiple meshes +export type RefMeshArray = React.MutableRefObject; + +// Array of 3D vectors, useful for handling points or positions +export type Vector3Array = THREE.Vector3[]; + +// Drag control type, either a valid DragControls instance or null +export type DragControl = DragControls | null; +export type RefDragControl = React.MutableRefObject; + + +/** Primitive Types with Mutable References **/ + +export type String = string; +export type RefStringArray = React.MutableRefObject; +export type RefString = React.MutableRefObject; + +export type Boolean = boolean; +export type RefBoolean = React.MutableRefObject; + +export type Number = number; +export type NumberArray = number[]; + +// Reference for the THREE.js Raycaster, useful in handling ray intersections +export type RefRaycaster = React.MutableRefObject; + +// Camera reference, supporting both perspective and basic cameras +export type RefCamera = React.MutableRefObject; + + +/** Three.js Root State Management **/ + +// Root state of the @react-three/fiber instance, providing context of the scene +export type ThreeState = RootState; + + +/** Point and Line Types for Spatial Geometry **/ + +// Defines a point in 3D space with metadata for unique identification +export type Point = [THREE.Vector3, string, number, string]; + +// Defines a line as two connected points, commonly used in scene building +export type Line = [Point, Point]; + +// Reference for a line, allowing dynamic updates +export type RefLine = React.MutableRefObject; + +// Collection of lines for structured geometry +export type Lines = Array; + + +/** Wall and Room Types for 3D Space Management **/ + +// Defines a wall with its geometry, position, rotation, material, and layer information +export type Wall = [THREE.ExtrudeGeometry, [number, number, number], [number, number, number], string, number]; + +// Collection of walls, useful in scene construction +export type Walls = Array; + +// Reference type for walls, allowing dynamic updates in React +export type RefWalls = React.MutableRefObject; + +// Room type, containing coordinates and layer metadata for spatial management +export type Rooms = Array<{ coordinates: Array<{ position: THREE.Vector3, uuid: string }>, layer: number }>; + +// Reference for room objects, enabling updates within React components +export type RefRooms = React.MutableRefObject, layer: number }>>; + +// Reference for lines, supporting React-based state changes +export type RefLines = React.MutableRefObject; + + +/** Floor Line Types for Layered Structures **/ + +// Floor line type for single lines on the floor level +export type OnlyFloorLine = Array; + +// Reference for floor lines, allowing manipulation in React +export type RefOnlyFloorLine = React.MutableRefObject; + +// Collection of lines across multiple floors, for multi-level structures +export type OnlyFloorLines = Array; + +// Reference for multi-level floor lines, allowing structured updates +export type RefOnlyFloorLines = React.MutableRefObject; + + +/** GeoJSON Line Integration **/ + +// Structure for representing GeoJSON lines, integrating external data sources +export type GeoJsonLine = { + line: any; + uuids: [string, string]; + layer: number; + type: string; +}; + + +/** State Management Types for React Components **/ + +// Dispatch types for number and boolean states, commonly used in React hooks +export type NumberIncrementState = React.Dispatch>; +export type BooleanState = React.Dispatch>; + +// Mutable reference for TubeGeometry, allowing dynamic geometry updates +export type RefTubeGeometry = React.MutableRefObject; + + +/** Floor Item Configuration **/ + +// Type for individual items placed on the floor, with positioning and rotation metadata +export type FloorItemType = { + modeluuid: string; + modelname: string; + position: [number, number, number]; + rotation: { x: number; y: number; z: number }; + modelfileID?: string; + isLocked: boolean; + isVisible: boolean; +}; + +// Array of floor items for managing multiple objects on the floor +export type FloorItems = Array; + +// Dispatch type for setting floor item state in React +export type setFloorItemSetState = React.Dispatch>; + + +/** Asset Configuration for Loading and Positioning **/ + +// Configuration for assets, allowing model URLs, scaling, positioning, and types +interface AssetConfiguration { + modelUrl: string; + scale?: [number, number, number]; + csgscale?: [number, number, number]; + csgposition?: [number, number, number]; + positionY?: (intersectionPoint: { point: THREE.Vector3 }) => number; + type?: "Fixed-Move" | "Free-Move"; +} + +// Collection of asset configurations, keyed by unique identifiers +export type AssetConfigurations = { + [key: string]: AssetConfiguration; +}; + + +/** Wall Item Configuration **/ + +// Configuration for wall items, including model, scale, position, and rotation +interface WallItem { + type: "Fixed-Move" | "Free-Move" | undefined; + model?: THREE.Group; + modeluuid?: string + modelname?: string; + scale?: [number, number, number]; + csgscale?: [number, number, number]; + csgposition?: [number, number, number]; + position?: [number, number, number]; + quaternion?: Types.QuaternionType; +} + +// Collection of wall items, allowing for multiple items in a scene +export type wallItems = Array; + +// Dispatch for setting wall item state in React +export type setWallItemSetState = React.Dispatch>; + +// Dispatch for setting vector3 state in React +export type setVector3State = React.Dispatch>; + +// Dispatch for setting euler state in React +export type setEulerState = React.Dispatch>; + +// Reference type for wall items, allowing direct access to the mutable array +export type RefWallItems = React.MutableRefObject; + + +/** Wall and Item Selection State Management **/ + +// State management for selecting, removing, and indexing wall items +export type setRemoveLayerSetState = (layer: number | null) => void; +export type setSelectedWallItemSetState = (item: THREE.Object3D | null) => void; +export type setSelectedFloorItemSetState = (item: THREE.Object3D | null) => void; +export type setSelectedItemsIndexSetState = (index: number | null) => void; + +export type RefCSM = React.MutableRefObject; +export type RefCSMHelper = React.MutableRefObject; + +interface PathConnection { + fromPathUUID: string; + fromUUID: string; + toConnections: { + toPathUUID: string; + toUUID: string; + }[]; +} + +interface ConnectionStore { + connections: PathConnection[]; + setConnections: (connections: PathConnection[]) => void; + addConnection: (newConnection: PathConnection) => void; + removeConnection: (fromUUID: string, toUUID: string) => void; } \ No newline at end of file diff --git a/app/src/utils/contextmenuHandler.ts b/app/src/utils/contextmenuHandler.ts index 1f71466..e34d330 100644 --- a/app/src/utils/contextmenuHandler.ts +++ b/app/src/utils/contextmenuHandler.ts @@ -1,137 +1,137 @@ -import React, { useState } from "react"; - -interface HandleDivProps { - switchesRef: React.RefObject; - setMenuLeftPosition: React.Dispatch>; - setMenuTopPosition: React.Dispatch>; - setMenuVisible: React.Dispatch>; -} -// The functional component that handles right-click (contextmenu) events -export default function ContextMenuHandler({ - switchesRef, - setMenuLeftPosition, - setMenuTopPosition, - setMenuVisible, -}: HandleDivProps) { - const [width, setWidth] = useState(0); - const [height, setHeight] = useState(0); - - // Function to handle the contextmenu event when a right-click happens - const handleClick = (event: MouseEvent) => { - event.preventDefault(); - const targets = event.target as HTMLElement; - const isInsideSwitches = switchesRef.current?.contains( - targets as Node - ); - const rect = switchesRef.current?.getBoundingClientRect(); - if (!rect) return; - - const totalHeight = rect.height + rect.top; - - const totalWidth = rect.width + rect.left; - - // Calculate the new position for the context menu - if (isInsideSwitches) { - const yPosition = event.clientY; - const xPosition = event.clientX; - //for top contextmenu handling - - if ( - totalHeight - yPosition > 20 && - totalHeight - yPosition < 260 - ) { - const minTop = yPosition - 110; - setMenuTopPosition(minTop); - } else if ( - totalHeight - yPosition >= 260 && - yPosition > height - 73 - ) { - const minTop = yPosition + 115; - setMenuTopPosition(minTop); - } - - // for top contextmenu handling - if ( - totalWidth - xPosition > 500 && - totalWidth - xPosition < 900 - ) { - const minLeft = xPosition + 80; - setMenuLeftPosition(minLeft); - } else if ( - totalWidth - xPosition > 10 && - totalWidth - xPosition > 150 - ) { - const minLeft = xPosition + 80; - setMenuLeftPosition(minLeft); - } else { - const minLeft = xPosition - 80; - setMenuLeftPosition(minLeft); - } - // setMenuVisible(true); - } else { - setMenuVisible(false); - } - }; - React.useEffect(() => { - const element = switchesRef.current; - - // Create a resize observer - const resizeObserver = new ResizeObserver((entries) => { - if (entries.length > 0) { - // Update the width state with the new width of the element - const { width, height } = entries[0].contentRect; - setWidth(width); - setHeight(height); - } - }); - - // Start observing the element's width changes - if (element) { - resizeObserver.observe(element); - } - - // Cleanup observer on component unmount - return () => { - if (element) { - resizeObserver.unobserve(element); - - } - }; - }, [height, width]); - - React.useEffect(() => { - let drag = false; - let isRightMouseDown = false; - - const handleDown = (event: MouseEvent) => { - if (event.button === 2) { - isRightMouseDown = true; - drag = false; - } - } - - const handleUp = (event: MouseEvent) => { - if (event.button === 2) { - isRightMouseDown = false; - if (!drag) { - handleClick(event); - } - }; - } - - const handleMove = (event: MouseEvent) => { - if (isRightMouseDown) { drag = true; }; - } - - document.addEventListener("mousedown", handleDown); - document.addEventListener("mousemove", handleMove); - document.addEventListener("mouseup", handleUp); - - return () => { - document.removeEventListener("mousedown", handleDown); - document.removeEventListener("mousemove", handleMove); - document.removeEventListener("mouseup", handleUp); - }; - }, []); - return null; -} +import React, { useState } from "react"; + +interface HandleDivProps { + switchesRef: React.RefObject; + setMenuLeftPosition: React.Dispatch>; + setMenuTopPosition: React.Dispatch>; + setMenuVisible: React.Dispatch>; +} +// The functional component that handles right-click (contextmenu) events +export default function ContextMenuHandler({ + switchesRef, + setMenuLeftPosition, + setMenuTopPosition, + setMenuVisible, +}: HandleDivProps) { + const [width, setWidth] = useState(0); + const [height, setHeight] = useState(0); + + // Function to handle the contextmenu event when a right-click happens + const handleClick = (event: MouseEvent) => { + event.preventDefault(); + const targets = event.target as HTMLElement; + const isInsideSwitches = switchesRef.current?.contains( + targets as Node + ); + const rect = switchesRef.current?.getBoundingClientRect(); + if (!rect) return; + + const totalHeight = rect.height + rect.top; + + const totalWidth = rect.width + rect.left; + + // Calculate the new position for the context menu + if (isInsideSwitches) { + const yPosition = event.clientY; + const xPosition = event.clientX; + //for top contextmenu handling + + if ( + totalHeight - yPosition > 20 && + totalHeight - yPosition < 260 + ) { + const minTop = yPosition - 110; + setMenuTopPosition(minTop); + } else if ( + totalHeight - yPosition >= 260 && + yPosition > height - 73 + ) { + const minTop = yPosition + 115; + setMenuTopPosition(minTop); + } + + // for top contextmenu handling + if ( + totalWidth - xPosition > 500 && + totalWidth - xPosition < 900 + ) { + const minLeft = xPosition + 80; + setMenuLeftPosition(minLeft); + } else if ( + totalWidth - xPosition > 10 && + totalWidth - xPosition > 150 + ) { + const minLeft = xPosition + 80; + setMenuLeftPosition(minLeft); + } else { + const minLeft = xPosition - 80; + setMenuLeftPosition(minLeft); + } + // setMenuVisible(true); + } else { + setMenuVisible(false); + } + }; + React.useEffect(() => { + const element = switchesRef.current; + + // Create a resize observer + const resizeObserver = new ResizeObserver((entries) => { + if (entries.length > 0) { + // Update the width state with the new width of the element + const { width, height } = entries[0].contentRect; + setWidth(width); + setHeight(height); + } + }); + + // Start observing the element's width changes + if (element) { + resizeObserver.observe(element); + } + + // Cleanup observer on component unmount + return () => { + if (element) { + resizeObserver.unobserve(element); + + } + }; + }, [height, width]); + + React.useEffect(() => { + let drag = false; + let isRightMouseDown = false; + + const handleDown = (event: MouseEvent) => { + if (event.button === 2) { + isRightMouseDown = true; + drag = false; + } + } + + const handleUp = (event: MouseEvent) => { + if (event.button === 2) { + isRightMouseDown = false; + if (!drag) { + handleClick(event); + } + }; + } + + const handleMove = (event: MouseEvent) => { + if (isRightMouseDown) { drag = true; }; + } + + document.addEventListener("mousedown", handleDown); + document.addEventListener("mousemove", handleMove); + document.addEventListener("mouseup", handleUp); + + return () => { + document.removeEventListener("mousedown", handleDown); + document.removeEventListener("mousemove", handleMove); + document.removeEventListener("mouseup", handleUp); + }; + }, []); + return null; +} diff --git a/app/src/utils/indexDB/idbUtils.ts b/app/src/utils/indexDB/idbUtils.ts index bc7c30d..c9228d3 100644 --- a/app/src/utils/indexDB/idbUtils.ts +++ b/app/src/utils/indexDB/idbUtils.ts @@ -1,45 +1,45 @@ -const DB_NAME = 'GLTFStorage'; -const STORE_NAME = 'models'; -const DB_VERSION = 1; - -export function initializeDB(): Promise { - return new Promise((resolve, reject) => { - const request = indexedDB.open(DB_NAME, DB_VERSION); - - request.onupgradeneeded = () => { - const db = request.result; - if (!db.objectStoreNames.contains(STORE_NAME)) { - db.createObjectStore(STORE_NAME); - } - }; - - request.onsuccess = () => resolve(request.result); - request.onerror = () => reject(request.error); - }); -} - -export async function storeGLTF(key: string, file: Blob): Promise { - const db = await initializeDB(); - - return new Promise((resolve, reject) => { - const transaction = db.transaction(STORE_NAME, 'readwrite'); - const store = transaction.objectStore(STORE_NAME); - const request = store.put(file, key); - - request.onsuccess = () => resolve(); - request.onerror = () => reject(request.error); - }); -} - -export async function retrieveGLTF(key: string): Promise { - const db = await initializeDB(); - - return new Promise((resolve, reject) => { - const transaction = db.transaction(STORE_NAME, 'readonly'); - const store = transaction.objectStore(STORE_NAME); - const request = store.get(key); - - request.onsuccess = () => resolve(request.result as Blob | undefined); - request.onerror = () => reject(request.error); - }); +const DB_NAME = 'GLTFStorage'; +const STORE_NAME = 'models'; +const DB_VERSION = 1; + +export function initializeDB(): Promise { + return new Promise((resolve, reject) => { + const request = indexedDB.open(DB_NAME, DB_VERSION); + + request.onupgradeneeded = () => { + const db = request.result; + if (!db.objectStoreNames.contains(STORE_NAME)) { + db.createObjectStore(STORE_NAME); + } + }; + + request.onsuccess = () => resolve(request.result); + request.onerror = () => reject(request.error); + }); +} + +export async function storeGLTF(key: string, file: Blob): Promise { + const db = await initializeDB(); + + return new Promise((resolve, reject) => { + const transaction = db.transaction(STORE_NAME, 'readwrite'); + const store = transaction.objectStore(STORE_NAME); + const request = store.put(file, key); + + request.onsuccess = () => resolve(); + request.onerror = () => reject(request.error); + }); +} + +export async function retrieveGLTF(key: string): Promise { + const db = await initializeDB(); + + return new Promise((resolve, reject) => { + const transaction = db.transaction(STORE_NAME, 'readonly'); + const store = transaction.objectStore(STORE_NAME); + const request = store.get(key); + + request.onsuccess = () => resolve(request.result as Blob | undefined); + request.onerror = () => reject(request.error); + }); } \ No newline at end of file diff --git a/app/src/utils/outerClick.ts b/app/src/utils/outerClick.ts index c5a6f74..de8f7ef 100644 --- a/app/src/utils/outerClick.ts +++ b/app/src/utils/outerClick.ts @@ -1,29 +1,29 @@ -import React from "react"; - -interface OuterClickProps { - contextClassName: string; - setMenuVisible: React.Dispatch>; -} - -export default function OuterClick({ - contextClassName, - setMenuVisible, -}: OuterClickProps) { - const handleClick = (event: MouseEvent) => { - const targets = event.target as HTMLElement; - // Check if the click is outside the selectable-dropdown-wrapper - if (!targets.closest(`.${contextClassName}`)) { - setMenuVisible(false); // Close the menu by updating the state - } - }; - - // Add event listener on mount and remove it on unmount - React.useEffect(() => { - document.addEventListener("click", handleClick); - return () => { - document.removeEventListener("click", handleClick); - }; - }, []); - - return null; // This component doesn't render anything -} +import React from "react"; + +interface OuterClickProps { + contextClassName: string; + setMenuVisible: React.Dispatch>; +} + +export default function OuterClick({ + contextClassName, + setMenuVisible, +}: OuterClickProps) { + const handleClick = (event: MouseEvent) => { + const targets = event.target as HTMLElement; + // Check if the click is outside the selectable-dropdown-wrapper + if (!targets.closest(`.${contextClassName}`)) { + setMenuVisible(false); // Close the menu by updating the state + } + }; + + // Add event listener on mount and remove it on unmount + React.useEffect(() => { + document.addEventListener("click", handleClick); + return () => { + document.removeEventListener("click", handleClick); + }; + }, []); + + return null; // This component doesn't render anything +} diff --git a/compose.yaml b/compose.yaml index 9f6a00b..2b5e419 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,12 +1,13 @@ services: frontend: build: - context: ./frontend + context: ./app + dockerfile: Dockerfile args: - REACT_APP_SERVER_SOCKET_API_BASE_URL=185.100.212.76:8000 - REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000 - REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011 - container_name: dwinzo-frontend + container_name: dwinzo-beta stdin_open: true tty: true ports: @@ -16,7 +17,7 @@ services: - PORT=3000 - DOCSIFY_PORT=8201 volumes: - - ./frontend:/app + - ./app:/app volumes: frontend: