From d6a675bd0717d0d6e61d71570fc557940068126d Mon Sep 17 00:00:00 2001 From: "seunghyeok.lee@kt.com" Date: Tue, 26 Nov 2024 18:24:31 +0900 Subject: [PATCH] dobot robot arm add --- dobot-serial/.gitignore | 160 + dobot-serial/.idea/huenit-serial.iml | 9 + .../inspectionProfiles/Project_Default.xml | 6 + dobot-serial/.idea/misc.xml | 6 + dobot-serial/.idea/modules.xml | 8 + dobot-serial/.idea/vcs.xml | 6 + dobot-serial/.idea/workspace.xml | 53 + dobot-serial/.prettierignore | 10 + dobot-serial/.prettierrc.js | 28 + dobot-serial/LICENSE | 201 + dobot-serial/README.md | 15 + dobot-serial/_export.sh | 9 + dobot-serial/_purge.sh | 17 + dobot-serial/main/.env | 3 + dobot-serial/main/.env.production | 3 + dobot-serial/main/.eslintrc.js | 30 + dobot-serial/main/.gitignore | 34 + dobot-serial/main/app/layout.tsx | 17 + dobot-serial/main/app/page.tsx | 77 + dobot-serial/main/next-env.d.ts | 5 + dobot-serial/main/next.config.js | 12 + dobot-serial/main/package.json | 37 + dobot-serial/main/public/bluetooth.svg | 6 + dobot-serial/main/public/dobot.jpg | Bin 0 -> 17600 bytes dobot-serial/main/public/logo.png | Bin 0 -> 14942 bytes dobot-serial/main/public/usb.svg | 1 + dobot-serial/main/src/config.ts | 14 + dobot-serial/main/src/constant.ts | 12 + dobot-serial/main/src/hw/CommandRunner.ts | 205 + dobot-serial/main/src/hw/CommandRunnerBase.ts | 523 +++ dobot-serial/main/src/hw/HuenitParser.ts | 109 + dobot-serial/main/src/hw/WebSerialDevice.ts | 292 ++ dobot-serial/main/src/hw/command-util.ts | 16 + dobot-serial/main/src/hw/robot-controller.py | 61 + dobot-serial/main/src/hw/types.ts | 4 + dobot-serial/main/src/hw/ws.txt | 397 ++ dobot-serial/main/src/logger.ts | 1 + dobot-serial/main/src/theme/ThemeRegistry.tsx | 18 + dobot-serial/main/src/theme/theme.ts | 20 + dobot-serial/main/src/util/gen-id.ts | 5 + dobot-serial/main/src/util/misc.ts | 43 + dobot-serial/main/tsconfig.json | 21 + dobot-serial/package-lock.json | 898 ++++ dobot-serial/package.json | 18 + dobot-serial/pnpm-lock.yaml | 4088 +++++++++++++++++ dobot-serial/pnpm-workspace.yaml | 3 + dobot-serial/sub/eslint-config/README.md | 3 + dobot-serial/sub/eslint-config/library.js | 59 + dobot-serial/sub/eslint-config/next.js | 55 + dobot-serial/sub/eslint-config/package.json | 19 + .../sub/eslint-config/react-internal.js | 77 + dobot-serial/sub/typescript-config/base.json | 25 + .../sub/typescript-config/nextjs.json | 13 + .../sub/typescript-config/package.json | 9 + .../sub/typescript-config/react-library.json | 8 + dobot-serial/sub/typescript-config/vite.json | 24 + dobot-serial/sub/ui/.eslintrc.cjs | 11 + dobot-serial/sub/ui/package.json | 35 + .../sub/ui/src/components/ConnectButton.tsx | 105 + .../ui/src/components/HardwareImageBox.tsx | 37 + .../sub/ui/src/components/HardwareNameBox.tsx | 38 + .../sub/ui/src/components/MediaIconBox.tsx | 31 + dobot-serial/sub/ui/src/components/index.ts | 4 + dobot-serial/sub/ui/src/hooks/index.ts | 1 + dobot-serial/sub/ui/src/hooks/usePet.ts | 66 + dobot-serial/sub/ui/src/index.ts | 3 + dobot-serial/sub/ui/src/util/event-utils.ts | 33 + dobot-serial/sub/ui/src/util/index.ts | 4 + dobot-serial/sub/ui/src/util/misc-utils.ts | 90 + dobot-serial/sub/ui/src/util/sx-props.ts | 15 + dobot-serial/sub/ui/src/util/type-check.ts | 9 + dobot-serial/sub/ui/tsconfig.json | 8 + dobot-serial/tsconfig.json | 3 + dobot-serial/turbo.json | 20 + 74 files changed, 8306 insertions(+) create mode 100644 dobot-serial/.gitignore create mode 100644 dobot-serial/.idea/huenit-serial.iml create mode 100644 dobot-serial/.idea/inspectionProfiles/Project_Default.xml create mode 100644 dobot-serial/.idea/misc.xml create mode 100644 dobot-serial/.idea/modules.xml create mode 100644 dobot-serial/.idea/vcs.xml create mode 100644 dobot-serial/.idea/workspace.xml create mode 100644 dobot-serial/.prettierignore create mode 100644 dobot-serial/.prettierrc.js create mode 100644 dobot-serial/LICENSE create mode 100644 dobot-serial/README.md create mode 100755 dobot-serial/_export.sh create mode 100755 dobot-serial/_purge.sh create mode 100644 dobot-serial/main/.env create mode 100644 dobot-serial/main/.env.production create mode 100644 dobot-serial/main/.eslintrc.js create mode 100644 dobot-serial/main/.gitignore create mode 100644 dobot-serial/main/app/layout.tsx create mode 100644 dobot-serial/main/app/page.tsx create mode 100644 dobot-serial/main/next-env.d.ts create mode 100644 dobot-serial/main/next.config.js create mode 100644 dobot-serial/main/package.json create mode 100644 dobot-serial/main/public/bluetooth.svg create mode 100644 dobot-serial/main/public/dobot.jpg create mode 100644 dobot-serial/main/public/logo.png create mode 100644 dobot-serial/main/public/usb.svg create mode 100644 dobot-serial/main/src/config.ts create mode 100644 dobot-serial/main/src/constant.ts create mode 100644 dobot-serial/main/src/hw/CommandRunner.ts create mode 100644 dobot-serial/main/src/hw/CommandRunnerBase.ts create mode 100644 dobot-serial/main/src/hw/HuenitParser.ts create mode 100644 dobot-serial/main/src/hw/WebSerialDevice.ts create mode 100644 dobot-serial/main/src/hw/command-util.ts create mode 100755 dobot-serial/main/src/hw/robot-controller.py create mode 100644 dobot-serial/main/src/hw/types.ts create mode 100755 dobot-serial/main/src/hw/ws.txt create mode 100644 dobot-serial/main/src/logger.ts create mode 100644 dobot-serial/main/src/theme/ThemeRegistry.tsx create mode 100644 dobot-serial/main/src/theme/theme.ts create mode 100644 dobot-serial/main/src/util/gen-id.ts create mode 100644 dobot-serial/main/src/util/misc.ts create mode 100644 dobot-serial/main/tsconfig.json create mode 100644 dobot-serial/package-lock.json create mode 100644 dobot-serial/package.json create mode 100644 dobot-serial/pnpm-lock.yaml create mode 100644 dobot-serial/pnpm-workspace.yaml create mode 100644 dobot-serial/sub/eslint-config/README.md create mode 100644 dobot-serial/sub/eslint-config/library.js create mode 100644 dobot-serial/sub/eslint-config/next.js create mode 100644 dobot-serial/sub/eslint-config/package.json create mode 100644 dobot-serial/sub/eslint-config/react-internal.js create mode 100644 dobot-serial/sub/typescript-config/base.json create mode 100644 dobot-serial/sub/typescript-config/nextjs.json create mode 100644 dobot-serial/sub/typescript-config/package.json create mode 100644 dobot-serial/sub/typescript-config/react-library.json create mode 100644 dobot-serial/sub/typescript-config/vite.json create mode 100644 dobot-serial/sub/ui/.eslintrc.cjs create mode 100644 dobot-serial/sub/ui/package.json create mode 100644 dobot-serial/sub/ui/src/components/ConnectButton.tsx create mode 100644 dobot-serial/sub/ui/src/components/HardwareImageBox.tsx create mode 100644 dobot-serial/sub/ui/src/components/HardwareNameBox.tsx create mode 100644 dobot-serial/sub/ui/src/components/MediaIconBox.tsx create mode 100644 dobot-serial/sub/ui/src/components/index.ts create mode 100644 dobot-serial/sub/ui/src/hooks/index.ts create mode 100644 dobot-serial/sub/ui/src/hooks/usePet.ts create mode 100644 dobot-serial/sub/ui/src/index.ts create mode 100644 dobot-serial/sub/ui/src/util/event-utils.ts create mode 100644 dobot-serial/sub/ui/src/util/index.ts create mode 100644 dobot-serial/sub/ui/src/util/misc-utils.ts create mode 100644 dobot-serial/sub/ui/src/util/sx-props.ts create mode 100644 dobot-serial/sub/ui/src/util/type-check.ts create mode 100644 dobot-serial/sub/ui/tsconfig.json create mode 100644 dobot-serial/tsconfig.json create mode 100644 dobot-serial/turbo.json diff --git a/dobot-serial/.gitignore b/dobot-serial/.gitignore new file mode 100644 index 0000000..3b7e5ad --- /dev/null +++ b/dobot-serial/.gitignore @@ -0,0 +1,160 @@ +yarn.lock + +# Created by https://www.toptal.com/developers/gitignore/api/turbo,node,react +# Edit at https://www.toptal.com/developers/gitignore?templates=turbo,node,react + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +# .env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Node Patch ### +# Serverless Webpack directories +.webpack/ + +# Optional stylelint cache + +# SvelteKit build / generate output +.svelte-kit + +### react ### +.DS_* +**/*.backup.* +**/*.back.* + +node_modules + +*.sublime* + +psd +thumb +sketch + +### Turbo ### +# Turborepo task cache +.turbo + +# End of https://www.toptal.com/developers/gitignore/api/turbo,node,react diff --git a/dobot-serial/.idea/huenit-serial.iml b/dobot-serial/.idea/huenit-serial.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/dobot-serial/.idea/huenit-serial.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dobot-serial/.idea/inspectionProfiles/Project_Default.xml b/dobot-serial/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/dobot-serial/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/dobot-serial/.idea/misc.xml b/dobot-serial/.idea/misc.xml new file mode 100644 index 0000000..e0844bc --- /dev/null +++ b/dobot-serial/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dobot-serial/.idea/modules.xml b/dobot-serial/.idea/modules.xml new file mode 100644 index 0000000..1f8eadf --- /dev/null +++ b/dobot-serial/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/dobot-serial/.idea/vcs.xml b/dobot-serial/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/dobot-serial/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dobot-serial/.idea/workspace.xml b/dobot-serial/.idea/workspace.xml new file mode 100644 index 0000000..50ef4e7 --- /dev/null +++ b/dobot-serial/.idea/workspace.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + 1708994103715 + + + + + + \ No newline at end of file diff --git a/dobot-serial/.prettierignore b/dobot-serial/.prettierignore new file mode 100644 index 0000000..199fda5 --- /dev/null +++ b/dobot-serial/.prettierignore @@ -0,0 +1,10 @@ +.next +public +static +node_modules +**/dist/** +*.png +*.svg +**/.turbo/** +**/build/** +**/dist/** \ No newline at end of file diff --git a/dobot-serial/.prettierrc.js b/dobot-serial/.prettierrc.js new file mode 100644 index 0000000..064c391 --- /dev/null +++ b/dobot-serial/.prettierrc.js @@ -0,0 +1,28 @@ +module.exports = { + printWidth: 100, + tabWidth: 2, + trailingComma: 'all', + singleQuote: true, + bracketSpacing: true, + semi: false, + useTabs: false, + arrowParens: 'always', + endOfLine: 'lf', + proseWrap: 'preserve', + bracketSameLine: false, + overrides: [ + { + files: '*.json', + options: { + printWidth: 200, + tabWidth: 2, + }, + }, + { + files: ['*.mts', '*.cts', '*.ts', '*.tsx'], + options: { + parser: 'typescript', + }, + }, + ], // 특정 파일별로 옵션을 다르게 지정함, ESLint 방식 사용 +} diff --git a/dobot-serial/LICENSE b/dobot-serial/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/dobot-serial/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/dobot-serial/README.md b/dobot-serial/README.md new file mode 100644 index 0000000..15d1aaa --- /dev/null +++ b/dobot-serial/README.md @@ -0,0 +1,15 @@ +## TODO + +## huenit 제어 커맨드 예시 + +serial connection 완료 이후 + +```js +await hw.robothome() +await hw.moveG0(0, 180, 0) +await hw.suctionOn() +await hw.suctionOff() +await hw.moveGoDobot(10, 10, 10, 10) +await hw.testConnection() +await hw.moveDobot(100, 10, 10, 0) +``` diff --git a/dobot-serial/_export.sh b/dobot-serial/_export.sh new file mode 100755 index 0000000..8a252ef --- /dev/null +++ b/dobot-serial/_export.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -e + +SCRIPT_DIR=$(dirname "$(readlink -f "$0")") +cd "${SCRIPT_DIR}" + +pnpm install +pnpm build diff --git a/dobot-serial/_purge.sh b/dobot-serial/_purge.sh new file mode 100755 index 0000000..40f669d --- /dev/null +++ b/dobot-serial/_purge.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -e + +SCRIPT_DIR=$(dirname "$(readlink -f "$0")") +cd "${SCRIPT_DIR}" + + +rm -rf main/node_modules main/.next main/.turbo + +for f in sub/*; do + echo "rm -rf $f/node_modules $f/.turbo $f/dist" + rm -rf $f/node_modules $f/.turbo $f/dist +done + +echo "`pwd` : rm -rf node_modules" +rm -rf node_modules diff --git a/dobot-serial/main/.env b/dobot-serial/main/.env new file mode 100644 index 0000000..85f728b --- /dev/null +++ b/dobot-serial/main/.env @@ -0,0 +1,3 @@ +NEXT_PUBLIC_BASE_PATH=/ +NEXT_PUBLIC_PRODUCTION=false +NEXT_PUBLIC_DEBUG=true \ No newline at end of file diff --git a/dobot-serial/main/.env.production b/dobot-serial/main/.env.production new file mode 100644 index 0000000..29040d2 --- /dev/null +++ b/dobot-serial/main/.env.production @@ -0,0 +1,3 @@ +NEXT_PUBLIC_BASE_PATH=/aimk-server/d_/hw-iframe/dobot-serial +NEXT_PUBLIC_PRODUCTION=true +NEXT_PUBLIC_DEBUG=false diff --git a/dobot-serial/main/.eslintrc.js b/dobot-serial/main/.eslintrc.js new file mode 100644 index 0000000..c39d43b --- /dev/null +++ b/dobot-serial/main/.eslintrc.js @@ -0,0 +1,30 @@ +module.exports = { + root: true, + extends: ['@repo/eslint-config/next.js'], + parser: '@typescript-eslint/parser', + parserOptions: { + project: true, + }, + rules: { + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'warn', + 'react/no-unstable-nested-components': 'off', + 'no-lonely-if': 'off', + 'no-empty': 'off', + 'no-constant-binary-expression': 'off', + 'no-return-await': 'off', + 'unicorn/prefer-node-protocol': 'off', + '@typescript-eslint/prefer-optional-chain': 'off', + 'react/jsx-no-useless-fragment': 'off', + '@next/next/no-img-element': 'off', + '@typescript-eslint/no-dynamic-delete': 'off', + '@typescript-eslint/require-array-sort-compare': 'off', + 'jsx-a11y/iframe-has-title': 'off', + 'react/no-array-index-key': 'off', + '@typescript-eslint/ban-types': 'off', + 'no-param-reassign': 'off', + 'prefer-named-capture-group': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + 'jsx-a11y/no-autofocus': 'off', + }, +} diff --git a/dobot-serial/main/.gitignore b/dobot-serial/main/.gitignore new file mode 100644 index 0000000..1437c53 --- /dev/null +++ b/dobot-serial/main/.gitignore @@ -0,0 +1,34 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel diff --git a/dobot-serial/main/app/layout.tsx b/dobot-serial/main/app/layout.tsx new file mode 100644 index 0000000..7ff113a --- /dev/null +++ b/dobot-serial/main/app/layout.tsx @@ -0,0 +1,17 @@ +import ThemeRegistry from '@/theme/ThemeRegistry' +import type { Metadata } from 'next' + +export const metadata: Metadata = { + title: 'Codiny Hw Iframe', + description: 'codiny hw iframe', +} + +export default function RootLayout({ children }: { children: React.ReactNode }): JSX.Element { + return ( + + + {children} + + + ) +} diff --git a/dobot-serial/main/app/page.tsx b/dobot-serial/main/app/page.tsx new file mode 100644 index 0000000..31e8afd --- /dev/null +++ b/dobot-serial/main/app/page.tsx @@ -0,0 +1,77 @@ +'use client' + +import { HW_ID, HW_NAME } from '@/constant' +import { CommandRunner } from '@/hw/CommandRunner' +import { Box, TextField } from '@mui/material' +import { ConnectButton, HardwareImageBox, HardwareNameBox, MediaIconBox, usePet } from '@repo/ui' +import { useSearchParams } from 'next/navigation' +import { Suspense, useState } from 'react' +const LOGO_IMG_URL = 'dobot.jpg' + +const MEDIA_ICON = 'usb.svg' + +export default function Page() { + return ( + + + + ) +} + +function PageInternal() { + const { commandRunner, connectionState, pet } = usePet(HW_ID, CommandRunner, useSearchParams()) + + // State for the IP address + const [ipAddress, setIpAddress] = useState('') + + // Handler for IP address input change + const handleIpChange = (event) => { + setIpAddress(event.target.value) + } + + // Click handler for the Connect button + const handleClickConnectBtn = () => { + const runner = commandRunner + if (!runner) return + runner.testConnect(ipAddress) // Pass the IP address when connecting + } + + // Click handler for the Disconnect button + const handleClickDisconnectBtn = () => { + const runner = commandRunner + if (!runner) { + return + } + runner.disconnect() + } + + return ( + + + + + + {/* IP Address Input Box */} + + + + + + + ) +} diff --git a/dobot-serial/main/next-env.d.ts b/dobot-serial/main/next-env.d.ts new file mode 100644 index 0000000..4f11a03 --- /dev/null +++ b/dobot-serial/main/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/dobot-serial/main/next.config.js b/dobot-serial/main/next.config.js new file mode 100644 index 0000000..301ce67 --- /dev/null +++ b/dobot-serial/main/next.config.js @@ -0,0 +1,12 @@ +const BASE_PATH = process.env.NEXT_PUBLIC_BASE_PATH + +/** + * @type {import('next').NextConfig} + **/ +const nextConfig = { + reactStrictMode: false, + output: BASE_PATH === '/' ? 'standalone' : 'export', + basePath: BASE_PATH === '/' ? '' : BASE_PATH, +} + +module.exports = nextConfig diff --git a/dobot-serial/main/package.json b/dobot-serial/main/package.json new file mode 100644 index 0000000..e2093c3 --- /dev/null +++ b/dobot-serial/main/package.json @@ -0,0 +1,37 @@ +{ + "name": "web", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@emotion/cache": "^11.11.0", + "@emotion/react": "^11.11.1", + "@emotion/styled": "^11.11.0", + "@ktaicoder/hw-pet": "^1.2.9", + "@mui/material": "^5.15.17", + "@mui/material-nextjs": "^5.15.11", + "clsx": "^2.0.0", + "eventemitter3": "^5.0.1", + "next": "^14.2.3", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "rxjs": "^7.8.1" + }, + "devDependencies": { + "@next/eslint-plugin-next": "^14.2.3", + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@repo/ui": "workspace:*", + "@types/node": "^17.0.12", + "@types/react": "^18.3.2", + "@types/react-dom": "^18.3.0", + "@types/w3c-web-serial": "^1.0.6", + "@types/web-bluetooth": "^0.0.20", + "typescript": "^5.3.3" + } +} diff --git a/dobot-serial/main/public/bluetooth.svg b/dobot-serial/main/public/bluetooth.svg new file mode 100644 index 0000000..b43d8ee --- /dev/null +++ b/dobot-serial/main/public/bluetooth.svg @@ -0,0 +1,6 @@ + + + diff --git a/dobot-serial/main/public/dobot.jpg b/dobot-serial/main/public/dobot.jpg new file mode 100644 index 0000000000000000000000000000000000000000..803f52ea49477da07dc0225731ed5ecb93a7b763 GIT binary patch literal 17600 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 ZUY<|KUlf*);4Mjz6yB-IR7snL|33#N%k}^O literal 0 HcmV?d00001 diff --git a/dobot-serial/main/public/logo.png b/dobot-serial/main/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5e5e0ed9d45942a3f29458158c6403afc36d9593 GIT binary patch literal 14942 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 literal 0 HcmV?d00001 diff --git a/dobot-serial/main/public/usb.svg b/dobot-serial/main/public/usb.svg new file mode 100644 index 0000000..ba28465 --- /dev/null +++ b/dobot-serial/main/public/usb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dobot-serial/main/src/config.ts b/dobot-serial/main/src/config.ts new file mode 100644 index 0000000..7ca4556 --- /dev/null +++ b/dobot-serial/main/src/config.ts @@ -0,0 +1,14 @@ +import { logger } from './logger' + +const basePath: string = process.env.NEXT_PUBLIC_BASE_PATH ?? '/' +const isProduction: boolean = process.env.NEXT_PUBLIC_PRODUCTION === 'true' +const isDebug: boolean = process.env.NEXT_PUBLIC_DEBUG === 'true' + +const config = { + basePath, + isProduction, + isDebug, +} + +logger.debug('config=', config) +export default config diff --git a/dobot-serial/main/src/constant.ts b/dobot-serial/main/src/constant.ts new file mode 100644 index 0000000..52e4a35 --- /dev/null +++ b/dobot-serial/main/src/constant.ts @@ -0,0 +1,12 @@ +/** + * hardware id + */ +export const HW_ID = 'dobot-serial' + +/** + * hardware name + */ +export const HW_NAME = { + en: 'dobot', + ko: '두봇', +} diff --git a/dobot-serial/main/src/hw/CommandRunner.ts b/dobot-serial/main/src/hw/CommandRunner.ts new file mode 100644 index 0000000..df223d4 --- /dev/null +++ b/dobot-serial/main/src/hw/CommandRunner.ts @@ -0,0 +1,205 @@ +import { CommandRunnerBase } from './CommandRunnerBase' + +/** + * Inherits from the CommandRunnerBase class. + * CommandRunnerBase handles the aspects related to the connection with hardware, + * and this class handles the remaining commands that are sent to the hardware. + */ +export class CommandRunner extends CommandRunnerBase { + async timeSleep(t: number): Promise { + await new Promise((resolve) => { + setTimeout(resolve, t * 1000) + }) + } + + private ipAddress: string | null = null + + // IP 주소를 설정하는 함수 + setIpAddress(ipAddress: string) { + this.ipAddress = ipAddress + } + + // IP 주소를 가져오는 함수 + getIpAddress(): string | null { + return this.ipAddress + } + + testConnect = async (ipAddress: string): Promise => { + if (!ipAddress) { + console.error('IP address is required.') + return false + } + + // IP 주소 저장 + this.setIpAddress(ipAddress) + + try { + const url = `http://${ipAddress}/connect` + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ port: '/dev/ttyUSB0' }), // JSON 데이터를 본문에 포함 + }) + + if (response.ok) { + const data = await response.json() + console.log('Response:', data) + } else { + console.error('Error:', response.statusText) + } + + return true + } catch (error) { + console.error('Error connecting to device:', error) + //this.updateConnectionState_('disconnected') + return false + } + } + + testDisconnect = async (): Promise => { + if (!this.ipAddress) { + console.error('IP address is not set.') + return false + } + + try { + const url = `http://${this.ipAddress}/disconnect` + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ port: '/dev/ttyUSB0' }), // JSON 데이터를 본문에 포함 + }) + + if (response.ok) { + const data = await response.json() + console.log('Response:', data) + } else { + console.error('Error:', response.statusText) + } + + return true + } catch (error) { + console.error('Error connecting to device:', error) + //this.updateConnectionState_('disconnected') + return false + } + } + + pose = async (): Promise => { + if (!this.ipAddress) { + console.error('IP address is not set.') + return + } + + try { + const url = `http://${this.ipAddress}/pose` + const response = await fetch(url, { + method: 'GET', + }) + + if (!response.ok) { + console.error(`Failed to fetch pose: ${response.statusText}`) + return + } + + const responseData = await response.json() + console.log('Pose Response:', responseData) + } catch (error) { + console.error('Error fetching pose:', error) + } + } + + moveRobot = async (x, y, z, r) => { + if (!this.ipAddress) { + console.error('IP address is not set.') + return + } + + try { + const url = `http://${this.ipAddress}/move` + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + x: x, + y: y, + z: z, + r: r, + wait: true, // 기본값으로 설정 + }), + }) + + if (!response.ok) { + console.error(`Failed to move robot: ${response.statusText}`) + return false + } + + const responseData = await response.json() + console.log('Move Response:', responseData) + return true + } catch (error) { + console.error('Error moving the robot:', error) + return false + } + } + + suckOn = async (): Promise => { + if (!this.ipAddress) { + console.error('IP address is not set.') + return + } + + try { + const url = `http://${this.ipAddress}/suckOn` + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }) + + if (!response.ok) { + console.error(`Failed to turn suction on: ${response.statusText}`) + return + } + + const responseData = await response.json() + console.log('Suction On Response:', responseData) + } catch (error) { + console.error('Error turning suction on:', error) + } + } + + suckOff = async (): Promise => { + if (!this.ipAddress) { + console.error('IP address is not set.') + return + } + + try { + const url = `http://${this.ipAddress}/suckOff` + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }) + + if (!response.ok) { + console.error(`Failed to turn suction off: ${response.statusText}`) + return + } + + const responseData = await response.json() + console.log('Suction Off Response:', responseData) + } catch (error) { + console.error('Error turning suction off:', error) + } + } +} diff --git a/dobot-serial/main/src/hw/CommandRunnerBase.ts b/dobot-serial/main/src/hw/CommandRunnerBase.ts new file mode 100644 index 0000000..a730fc4 --- /dev/null +++ b/dobot-serial/main/src/hw/CommandRunnerBase.ts @@ -0,0 +1,523 @@ +import { logger } from '@/logger' +import { genId } from '@/util/gen-id' +import { chr, errmsg } from '@/util/misc' +import type { + ConnectionState, + HPetNotifiyEventDefinition, + IHPetCommandRunner, + IHPetContext, + IParentSender, +} from '@ktaicoder/hw-pet' +import { HPetNotifyEventKeys } from '@ktaicoder/hw-pet' +import { sleepAsync } from '@repo/ui' +import type { EventEmitter } from 'eventemitter3' +import { + BehaviorSubject, + EMPTY, + Subject, + Subscription, + concatMap, + distinctUntilChanged, + filter, + firstValueFrom, + from, + map, + switchMap, + take, + takeUntil, + tap, + type Observable, + of, +} from 'rxjs' +import { HuenitParser } from './HuenitParser' +import { WebSerialDevice } from './WebSerialDevice' +import { openSerialDevice } from './command-util' +import type { BufferTimestamped } from './types' +import { timeout, catchError } from 'rxjs/operators' + +type TxDataType = number[] | Uint8Array | string +type TxRequest = { + requestId: string + debugCmd: string + data: TxDataType +} + +/** + * Class for sending commands to the hardware. + * Add the necessary commands here. + * Write the method names the same as the commands. + * + * Lifecycle methods: init(), destroy() + * Mandatory implementation methods: getConnectionState(), getHwId(), connect(), disconnect() + * Additional commands are the remaining methods other than the ones mentioned above (e.g., echo). + */ +export class CommandRunnerBase implements IHPetCommandRunner { + private stopped$ = new BehaviorSubject(false) + + /** + * 연결 상태 + */ + private connectionState: ConnectionState = 'disconnected' + + /** + * 하드웨어 ID + */ + private hwId: string + + /** + * 부모 프레임에 데이터 전송하는 도우미 객체 + */ + private toParent: IParentSender + + /** + * 연결 상태 등을 부모 프레임에 notify하기 위한 이벤트 객체 + */ + private notifyEvents: EventEmitter + + /** + * 시리얼 디바이스 + */ + private device_?: WebSerialDevice + + /** + * 연결이 해제될 때 호출될 함수 + */ + private disposeFn_?: VoidFunction + + /** + * rxLoop 리소스 해제 함수 + */ + private rxLoopDisposeFn_?: VoidFunction + + /** + * 하드웨어로부터 수신된 데이터 + * 수신된 raw data를 HuenitParser로 파싱한 데이터 + */ + private rxPacket$ = new Subject() + + /** + * 디바이스 쓰기 큐의 리소스 해제 함수 + */ + private txRequestQueueDisposeFn_?: VoidFunction + + /** + * 디바이스 쓰기 큐 + */ + private dataToDevice$ = new Subject() + + /** + * 디바이스로부터 수신된 데이터 + */ + private dataFromDevice$ = new Subject<{ + requestId: string + returnData: Uint8Array | null + }>() + + constructor(options: IHPetContext) { + const { hwId, toParent, notifyEvents, commandEvents, uiEvents } = options + + this.hwId = hwId + this.toParent = toParent + this.notifyEvents = notifyEvents + // commandEvents: 부모 프레임에서 전달되는 명령의 이벤트들 + // notifyEvents: 부모 프레임에 전달하는 연결 상태등의 notification 이벤트들 + // uiEvents: iframe의 ui와 상호작용할 수 있는 이벤트, 필요한 경우에만 사용 + } + + /** + * Lifecycle function, Automatically called. + * An essential function that must be implemented. + * Called once before communicating with parent frame (CODINY). + * Initialization tasks, such as registering event listeners, can be performed here. + */ + init = async (): Promise => { + logger.debug('CommandRunner.init()') + } + + /** + * Lifecycle function, Automatically called. + * An essential function that must be implemented. + * Called once after the connection with the hardware is terminated. + * Cleanup tasks, such as unregistering event listeners, can be performed here. + */ + destroy = async () => { + logger.debug('CommandRunner.destroy()') + } + + /** + * Update the connection state variable, + * emit an event if the connection state has changed, + * and notify the parent frame (CODINY). + * @param state - The connection state + */ + private updateConnectionState_ = (state: ConnectionState) => { + if (state !== this.connectionState) { + this.connectionState = state + this.notifyEvents.emit(HPetNotifyEventKeys.connectionStateChanged, this.connectionState) + + // notify to parent frame (CODINY) + this.toParent.notifyConnectionState(this.connectionState) + } + } + + /** + * command: getConnectionState + * + * get current connection state + * An essential function that must be implemented. + * The return value is automatically sent to the parent frame (CODINY) + * @returns ConnectionState - connection state + */ + getConnectionState = async (): Promise => { + return this.connectionState + } + + /** + * command: getHwId + * + * get hardware id + * An essential function that must be implemented. + * The return value is automatically sent to the parent frame (CODINY) + * @returns string - hwId + */ + getHwId = async (): Promise => { + return this.hwId + } + + get stopped() { + return this.stopped$.value + } + + protected registerListeners_ = (device: WebSerialDevice) => { + const subscription = new Subscription() + + // 디바이스의 상태가 변경될때 콜백 호출 + subscription.add( + device.observeDeviceState().subscribe((state) => { + if (state === 'opened') { + this.onConnected_(device) + } else if (state === 'closed') { + this.onDisconnected_() + } + }), + ) + + this.disposeFn_ = () => { + subscription.unsubscribe() + } + } + + /** + * command: connect + * + * Function to connect to the hardware. + * Check the connection status in ricConnector.setEventListener(). + * An essential function that must be implemented. + * @returns The return value is meaningless. + */ + connect = async (): Promise => { + let port: SerialPort | undefined + + try { + port = await openSerialDevice() + if (!port) return false + } catch (ignore) { + logger.debug(errmsg(ignore)) + } + + if (!port) { + return false + } + + this.updateConnectionState_('connecting') + const device = new WebSerialDevice() + this.device_ = device + this.registerListeners_(device) + device.open(port, { baudRate: 115200 }) + + // 연결이 되면 onConnected_() 가 호출되고, + // 연결이 실패하면 onDisconnected_() 가 호출됩니다 + return true + } + + /** + * 디바이스 콜백 - 연결됨 + */ + protected onConnected_ = async (device: WebSerialDevice) => { + this.stopped$.next(false) + this.device_ = device + this.updateConnectionState_('connected') + + // 하드웨어로부터 수신된 데이터를 처리한다 + this.rxLoop_() + + // 하드웨어 쓰기 요청이 도착하면 + // 하나씩 순차적으로 처리한다(concatMap) + const subscription = new Subscription() + subscription.add( + this.dataToDevice$ + .pipe( + concatMap((request) => from(this.handleTxRequest_(request))), + takeUntil(this.closeTrigger_()), + ) + .subscribe(), + ) + this.txRequestQueueDisposeFn_ = () => { + subscription.unsubscribe() + } + } + + /** + * 디바이스 콜백 - 연결이 끊어짐 + */ + protected onDisconnected_ = async () => { + this.disconnect() + } + + /** + * Observable's destroy trigger + */ + private closeTrigger_ = (): Observable => { + return this.stopped$.pipe(filter(Boolean), take(1)) + } + + /** + * 디바이스에 데이터를 전송합니다 + * Send values to the device + */ + protected writeRaw_ = async (values: number[] | Uint8Array | string): Promise => { + const device = this.device_ + // 디바이스에 연결되지 않은 상태 + if (!device) { + logger.debug('writeRaw_(): ignore, device not connected') + return + } + + // 디바이스 중지 중 + if (this.stopped$.value) { + logger.debug('writeRaw_(): ignore, stopping...') + return + } + + if (typeof values === 'string') { + await device.write(new Uint8Array(values.split('').map(chr))) + } else if (Array.isArray(values)) { + await device.write(new Uint8Array(values)) + } else { + await device.write(values) + } + } + + /** + * 하드웨어 쓰기 요청을 처리합니다. + * 하드웨어에 데이터를 전송한 후, 하드웨어로부터 응답을 기다립니다. + */ + private handleTxRequest_ = async (request: TxRequest): Promise => { + const { debugCmd, data, requestId } = request + const startTime = Date.now() + const values = typeof data === 'string' ? new Uint8Array(data.split('').map(chr)) : data + logger.debug(`${debugCmd}: write start: ${num2str(values)}`) + await this.writeRaw_(values) + if (this.stopped$.value) { + logger.debug(`${debugCmd} write canceled`) + return null + } + const returnData = await this.readNext_() + if (this.stopped$.value) { + logger.debug(`${debugCmd} write canceled`) + return null + } + const diff = Date.now() - startTime + logger.debug(`${debugCmd}: \t\texecution time: ${diff}ms, response: ${num2str(returnData)}`) + this.dataFromDevice$.next({ + requestId, + returnData, + }) + return returnData + } + + /** + * 하드웨어에 쓰기 요청을 enque 합니다. + * @param debugCmd - 디버그용 명령어 + * @param values - 하드웨어에 전송할 데이터 + * @param afterDelayMillis - 명령을 실행한 후에 sleep 할 시간 + */ + + protected write_ = async ( + commandId: number, + values: Uint8Array, + afterDelayMillis = 0, + isQueued = false, + ): Promise => { + if (this.stopped) { + console.log('Execution stopped') + return null + } + + const requestId = genId() + console.log('Generated Request ID:', requestId) + + const packetLength = values.length + 3 + const message = new Uint8Array([ + 0xaa, + 0xaa, + packetLength, + commandId, + 1, + isQueued ? 1 : 0, + ...values, + 0, + ]) + + // Calculate checksum as two's complement + message[message.length - 1] = (~message.reduce((sum, byte) => sum + byte, 0) + 1) & 0xff + console.log('Message with checksum:', message) + + this.dataToDevice$.next({ + requestId, + data: message, + debugCmd: `CmdID ${commandId}`, + }) + console.log('Data sent to device') + + try { + const result = await firstValueFrom( + this.dataFromDevice$.pipe( + filter((it) => it.requestId === requestId), + map((it) => it.returnData), + takeUntil(this.closeTrigger_()), + timeout(5000), // Extended timeout + catchError((err) => { + console.error('Response timeout or error:', err) + return of(null as Uint8Array | null) // Explicitly casting to the correct type + }), + ), + ) + + if (!result) { + console.log('No result received') + return null + } + + console.log('Result received:', result) + + if (!this.stopped && afterDelayMillis > 0) { + console.log(`Command ${commandId}: \t\tsleep ${afterDelayMillis}ms`) + await sleepAsync(afterDelayMillis) + } + + return result + } catch (err) { + console.log('Error in write_:', err) + logger.debug('write fail:', errmsg(err)) + } + + return null + } + + /** + * 하드웨어로부터 도착한 데이터를 처리합니다. + * 개행문자를 구분자로 파싱하여 패킷(Uint8Array)을 만듭니다. + */ + private rxLoop_ = () => { + const device = this.device_ + if (!device) { + logger.debug('rxLoop_(): device is not opened') + return + } + + const subscription = new Subscription() + subscription.add( + device + .observeOpenedOrNot() + .pipe( + distinctUntilChanged(), + switchMap((opened) => (opened ? device.observeRawData() : EMPTY)), + map((timestamped) => timestamped.dataBuffer), + HuenitParser.parse(), + tap((dataBuffer) => { + this.rxPacket$.next({ timestamp: Date.now(), dataBuffer }) + }), + takeUntil(this.closeTrigger_()), + ) + .subscribe(), + ) + + this.rxLoopDisposeFn_ = () => { + subscription.unsubscribe() + } + } + + /** + * 하드웨어로부터 수신된 데이터를 가져옵니다. + * 현재 시점 이후에 수신된 첫번째 데이터만 가져옵니다. + */ + private readNext_ = async (): Promise => { + if (this.stopped) return null + const now = Date.now() + try { + return await firstValueFrom( + this.rxPacket$.pipe( + filter((it) => it.timestamp >= now), + take(1), + map((it) => it.dataBuffer), + ), + ) + } catch (err) { + logger.debug('read failed', err) + } + return null + } + + /** + * command: disconnect + * + * Function to disconnect from the hardware. + * An essential function that must be implemented. + * @returns The return value is meaningless. + */ + disconnect = async () => { + this.stopped$.next(true) + if (this.disposeFn_) { + this.disposeFn_() + this.disposeFn_ = undefined + } + + if (this.rxLoopDisposeFn_) { + this.rxLoopDisposeFn_() + this.rxLoopDisposeFn_ = undefined + } + + if (this.txRequestQueueDisposeFn_) { + this.txRequestQueueDisposeFn_() + this.txRequestQueueDisposeFn_ = undefined + } + + if (this.device_) { + await this.device_.close() + this.device_ = undefined + } + + // When changing the connection state, be sure to call updateConnectionState_() + this.updateConnectionState_('disconnected') + } +} + +function num2str(data: number[] | Uint8Array | null) { + if (!data) { + return '' + } + const msg1 = data.join(' ') + let msg2: string[] = [] + for (let i = 0; i < data.length; i++) { + const c = data[i] + if (c === 10) { + msg2.push('\\n') + } else if (c === 13) { + msg2.push('\\r') + } else { + msg2.push(String.fromCharCode(c)) + } + } + return `[${msg1}] '${msg2.join('')}'` +} diff --git a/dobot-serial/main/src/hw/HuenitParser.ts b/dobot-serial/main/src/hw/HuenitParser.ts new file mode 100644 index 0000000..279a3c1 --- /dev/null +++ b/dobot-serial/main/src/hw/HuenitParser.ts @@ -0,0 +1,109 @@ +import { arrayConcat, arrayIndexOf, chr } from '@/util/misc' +import { Observable } from 'rxjs' + +// packet delimiter +const DELIMITER = [chr('\n')] // new line character + +interface Options { + includeDelimiter: boolean + delimiter: Uint8Array +} + +type TransformFn = (upstream: Observable) => Observable + +type PacketHandlerFn = (packet: Uint8Array) => void + +/** + * This class is delimiter parser. + * This class can be used on different hardware by simply changing the delimiter. + */ +export class HuenitParser { + /** + * Intermediate buffer + */ + private buffer: Uint8Array + + /** + * Whether including delimiters + */ + private readonly includeDelimiter: boolean + + /** + * delimiter + */ + private readonly delimiter: Uint8Array + + /** + * packet callback + * This is called when the packet is created. + */ + private readonly packetCallback_: PacketHandlerFn + + /** + * constructor + */ + constructor(options: Options, packetCallback: PacketHandlerFn) { + this.buffer = new Uint8Array(0) + this.delimiter = options.delimiter + this.includeDelimiter = options.includeDelimiter + this.packetCallback_ = packetCallback + } + + /** + * This is called when data is received from the hardware. + */ + enqueue = (chunk: Uint8Array) => { + let data = arrayConcat(this.buffer, chunk) + let position = -1 + // eslint-disable-next-line no-constant-condition + while (true) { + position = arrayIndexOf(data, this.delimiter) + if (position === -1) { + break + } + + if (this.includeDelimiter) { + this.packetCallback_(data.slice(0, position + this.delimiter.length)) + } else { + this.packetCallback_(data.slice(0, position)) + } + data = data.slice(position + this.delimiter.length) + } + this.buffer = data + } + + /** + * rxjs operator function + * upstream = raw byte array + * downstream = packet + */ + static parse = (): TransformFn => { + return (upstream: Observable) => { + return new Observable((subscriber) => { + const handleParsedResult = (packet: Uint8Array) => { + if (!subscriber.closed && packet.byteLength > 0) { + subscriber.next(packet) + } + } + + const parser = new HuenitParser( + { + includeDelimiter: false, + delimiter: new Uint8Array(DELIMITER), + }, + handleParsedResult, + ) + + const subscription = upstream.subscribe({ + next: parser.enqueue, + error: subscriber.error, + complete: subscriber.complete, + }) + + return () => { + subscription.unsubscribe() + } + }) + } + } +} diff --git a/dobot-serial/main/src/hw/WebSerialDevice.ts b/dobot-serial/main/src/hw/WebSerialDevice.ts new file mode 100644 index 0000000..c0b8bfd --- /dev/null +++ b/dobot-serial/main/src/hw/WebSerialDevice.ts @@ -0,0 +1,292 @@ +import { sleepAsync } from '@repo/ui' +import type { Observable } from 'rxjs' +import { + BehaviorSubject, + EMPTY, + Subject, + distinctUntilChanged, + filter, + firstValueFrom, + map, + switchMap, + take, + timeout, +} from 'rxjs' +import type { BufferTimestamped } from './types' + +type HwDeviceState = 'opening' | 'opened' | 'closing' | 'closed' + +export class WebSerialDevice { + DEBUG = false + + private deviceState$ = new BehaviorSubject('closed') + + private deviceRawData$ = new Subject() + + private port_?: SerialPort + + private reader_?: ReadableStreamDefaultReader + + private writer_?: WritableStreamDefaultWriter + + private readLoopPromise_?: Promise + + getRawSerialPort = (): SerialPort | undefined => { + return this.port_ + } + + /** + * 디바이스의 상태 관찰 + */ + observeDeviceState = (): Observable => this.deviceState$.asObservable() + + /** + * 디바이스의 연결 여부 관찰 + */ + observeOpenedOrNot = (): Observable => + this.deviceState$.pipe(map((it) => it === 'opened')) + + /** + * 연결이 될 때까지 기다리기 + */ + waitUntilOpened = (timeoutMilli = 0): Promise => { + if (timeoutMilli > 0) { + return firstValueFrom( + this.deviceState$.pipe( + filter((it) => it === 'opened'), + take(1), + timeout({ first: timeoutMilli }), + map(() => true), + ), + ) + } else { + return firstValueFrom( + this.deviceState$.pipe( + filter((it) => it === 'opened'), + take(1), + map(() => true), + ), + ) + } + } + + /** + * 디바이스의 데이터 관찰 + */ + observeRawData = (): Observable => { + return this.deviceState$.pipe( + distinctUntilChanged(), + map((state) => state === 'opened'), + switchMap((isOpened) => { + return isOpened ? this.deviceRawData$.asObservable() : EMPTY + }), + ) + } + + /** + * 연결 여부 + */ + isOpened = (): boolean => { + return this.deviceState$.value === 'opened' + } + + private closeAndWait_ = async () => { + if (this.deviceState$.value === 'closed') return + if (this.deviceState$.value !== 'closing') { + if (this.DEBUG) console.log('WebSerialDevice.closeAndWait_()') + this.close() + } + await firstValueFrom(this.deviceState$.pipe(filter((it) => it === 'closed'))) + } + + /** + * 디바이스 열기 + */ + open = async (port: SerialPort, options: SerialOptions): Promise => { + if (this.DEBUG) console.log('WebSerialDevice.open()', options) + await this.closeAndWait_() + if (this.DEBUG) console.log('WebSerialDevice.open() opening') + this.deviceState$.next('opening') + + while (this.deviceState$.value !== 'closed' && this.deviceState$.value !== 'closing') { + if (!port.readable) { + try { + if (this.DEBUG) console.log('WebSerialDevice.open() : port.open() called') + await port.open(options) + } catch (err) { + console.log(err) + } + } + + if (port.readable) { + break + } + + if (!port.readable) { + console.warn('WebSerialDevice.open() : port.open() failed, port is not readable, retry') + // this.deviceState$.next('closed') + await sleepAsync(200) + continue + } + } + + if (this.deviceState$.value === 'opening' && port.readable) { + this.onOpened_(port) + } + } + + private onOpened_ = (port: SerialPort) => { + if (this.DEBUG) console.debug('WebSerialDevice.onOpened_()') + this.port_ = port + this.deviceState$.next('opened') + this.readLoopPromise_ = this.startReadLoop_() + } + + /** + * 시리얼포트 읽기 루프 실행 + */ + private startReadLoop_ = async () => { + while (this.deviceState$.value === 'opened') { + if (this.DEBUG) { + if (!this.port_) { + console.warn('WebSerialDevice.startReadLoop_() this.port_ is null') + } else if (!this.port_.readable) { + console.warn('WebSerialDevice.startReadLoop_() this.port_.readable is null') + } + } + + if (!this.port_ || !this.port_.readable) { + await sleepAsync(100) + continue + } + + if (this.DEBUG) console.log('WebSerialDevice.startReadLoop_() locked reader') + // 이미 시리얼포트에 락이 걸려있는 경우는 실패한다 + const reader = this.getReaderOrNull_(this.port_) + if (!reader) { + await sleepAsync(100) + continue + } + this.reader_ = reader + try { + await this.doReadFromReader_(reader) + console.log('doReadFromReader_() end! deviceState =' + this.deviceState$.value) + } catch (err) { + // Handle non-fatal + console.info('startReadLoop_(): ignore error', err) + } finally { + if (this.DEBUG) console.log('WebSerialDevice.startReadLoop_() reader.releaseLock()') + + this.reader_?.releaseLock() + this.reader_ = undefined + } + } + } + + private getReaderOrNull_(port: SerialPort): ReadableStreamDefaultReader | null { + const readable = port.readable + if (!readable) return null + try { + const reader = readable.getReader() + return reader + } catch (err) { + // 시리얼포트에 락이 걸려있음 + } + return null + } + + private doReadFromReader_ = async (reader: ReadableStreamDefaultReader) => { + // console.log(`XXX WebSerialDevice.doReadFromReader_(): ${this.deviceState$.value}`) + while (this.deviceState$.value === 'opened') { + const { value: dataBuffer, done } = await reader.read() + // console.log(`XXX WebSerialDevice. reader.read(): ${done ? 'done' : ''}, ${dataBuffer?.byteLength ?? -1} bytes`) + if (done) { + break + } + + if (dataBuffer) { + this.deviceRawData$.next({ timestamp: Date.now(), dataBuffer }) + } + } + } + + /** + * 시리얼포트에 데이터 전송 + * @param value data to send + * @returns Promise + */ + write = async (value: Uint8Array): Promise => { + const port = this.port_ + if (!port) { + console.warn('WebSerialDevice.write() : port is not bound') + return + } + + if (!port.writable) { + console.warn('WebSerialDevice.write() : port is not writable') + return + } + + if (port.writable.locked) { + console.warn('WebSerialDevice.write() : port is locked') + await sleepAsync(100) + return + } + const writer = port.writable.getWriter() + try { + this.writer_ = writer + await writer.write(value) + } finally { + writer.releaseLock() + this.writer_ = undefined + } + } + + /** + * 디바이스 닫기 + */ + close = async () => { + if (this.DEBUG) console.log('WebSerialDevice.close() currentState=' + this.deviceState$.value) + if (this.deviceState$.value === 'closed') { + // console.log('ignore close, already closed') + return + } + + if (this.deviceState$.value === 'closing') { + console.log('ignore close, already closing') + return + } + + this.deviceState$.next('closing') + try { + if (this.reader_) { + await this.reader_.cancel() + this.reader_ = undefined + } + + if (this.readLoopPromise_) { + await this.readLoopPromise_.catch(() => { + /* ignore error */ + }) + this.readLoopPromise_ = undefined + } + + if (this.writer_) { + if (!this.writer_.closed) { + await this.writer_.close() + } + this.writer_ = undefined + } + + if (this.port_) { + await this.port_.close().catch(() => { + /* ignore error */ + }) + this.port_ = undefined + } + } finally { + if (this.DEBUG) console.log('WebSerialDevice closed') + this.deviceState$.next('closed') + } + } +} diff --git a/dobot-serial/main/src/hw/command-util.ts b/dobot-serial/main/src/hw/command-util.ts new file mode 100644 index 0000000..05e4744 --- /dev/null +++ b/dobot-serial/main/src/hw/command-util.ts @@ -0,0 +1,16 @@ +import { errmsg } from '@/util/misc' + +export async function openSerialDevice(): Promise { + try { + if ('serial' in navigator) { + return await navigator.serial.requestPort() + } + console.error('Serial API is not supported in this browser.') + return undefined + } catch (err) { + if (errmsg(err) === 'No port selected by the user') { + return undefined + } + throw err + } +} diff --git a/dobot-serial/main/src/hw/robot-controller.py b/dobot-serial/main/src/hw/robot-controller.py new file mode 100755 index 0000000..83bf5f2 --- /dev/null +++ b/dobot-serial/main/src/hw/robot-controller.py @@ -0,0 +1,61 @@ +# robot_controller.py +import sys +import json +import asyncio +from time import sleep + +class RobotController: + def __init__(self): + self.command_queue = asyncio.Queue() + self.serial_data = None + + async def process_command(self, command): + try: + cmd_type = command.get('type') + + if cmd_type == 'serial': + # 시리얼 데이터 저장 + self.serial_data = command.get('data') + return {'status': 'success', 'type': 'serial_stored'} + + if cmd_type == 'move': + # 시리얼 연결을 통해 로봇으로 명령 전송 + if self.serial_data: + # 실제로는 여기서 시리얼 데이터를 사용하여 로봇과 통신 + params = command.get('params', {}) + return { + 'status': 'success', + 'command': cmd_type, + 'params': params + } + else: + return {'status': 'error', 'message': 'No serial connection'} + + return {'status': 'error', 'message': 'Unknown command'} + + except Exception as e: + return {'status': 'error', 'message': str(e)} + + async def run(self): + while True: + try: + line = await self.get_input() + if not line: + continue + + command = json.loads(line) + result = await self.process_command(command) + + print(json.dumps(result)) + sys.stdout.flush() + + except Exception as e: + print(json.dumps({'status': 'error', 'message': str(e)})) + sys.stdout.flush() + + async def get_input(self): + return await asyncio.get_event_loop().run_in_executor(None, sys.stdin.readline) + +if __name__ == '__main__': + controller = RobotController() + asyncio.get_event_loop().run_until_complete(controller.run()) diff --git a/dobot-serial/main/src/hw/types.ts b/dobot-serial/main/src/hw/types.ts new file mode 100644 index 0000000..b90cc32 --- /dev/null +++ b/dobot-serial/main/src/hw/types.ts @@ -0,0 +1,4 @@ +export type BufferTimestamped = { + timestamp: number + dataBuffer: Uint8Array +} diff --git a/dobot-serial/main/src/hw/ws.txt b/dobot-serial/main/src/hw/ws.txt new file mode 100755 index 0000000..0f23d05 --- /dev/null +++ b/dobot-serial/main/src/hw/ws.txt @@ -0,0 +1,397 @@ +네, 모든 컴포넌트를 서버에서 실행하고 시리얼 통신만 클라이언트에서 처리하는 방식으로 구현할 수 있습니다. 이를 위해서는 웹시리얼 API를 활용해야 합니다. + + + +```javascript +// server/index.js +const express = require('express'); +const { Server } = require('ws'); +const http = require('http'); +const { spawn } = require('child_process'); +const cors = require('cors'); + +const app = express(); +const server = http.createServer(app); +const wss = new Server({ server }); + +app.use(cors()); +app.use(express.json()); + +// 로봇 연결 관리 +class RobotManager { + constructor() { + this.robots = new Map(); // robotId -> { pythonProcess, webSocket } + this.serialConnections = new Map(); // robotId -> webSocket (browser serial connection) + } + + startPythonProcess(robotId) { + if (this.robots.has(robotId)) { + return; + } + + const pythonProcess = spawn('python', ['robot_controller.py']); + + pythonProcess.stdout.on('data', (data) => { + const response = data.toString().trim(); + // 시리얼 연결된 브라우저로 결과 전송 + const serialWs = this.serialConnections.get(robotId); + if (serialWs) { + serialWs.send(JSON.stringify({ type: 'response', data: response })); + } + }); + + pythonProcess.stderr.on('data', (data) => { + console.error(`Python Error (${robotId}):`, data.toString()); + }); + + this.robots.set(robotId, { pythonProcess }); + } + + stopPythonProcess(robotId) { + const robot = this.robots.get(robotId); + if (robot && robot.pythonProcess) { + robot.pythonProcess.kill(); + this.robots.delete(robotId); + } + } + + registerSerialConnection(robotId, ws) { + this.serialConnections.set(robotId, ws); + // Python 프로세스가 없다면 시작 + if (!this.robots.has(robotId)) { + this.startPythonProcess(robotId); + } + } + + removeSerialConnection(robotId) { + this.serialConnections.delete(robotId); + // 연결된 브라우저가 없으면 Python 프로세스도 종료 + if (!this.serialConnections.has(robotId)) { + this.stopPythonProcess(robotId); + } + } + + sendCommand(robotId, command) { + const robot = this.robots.get(robotId); + if (robot && robot.pythonProcess) { + robot.pythonProcess.stdin.write(JSON.stringify(command) + '\n'); + return true; + } + return false; + } +} + +const robotManager = new RobotManager(); + +// WebSocket 연결 처리 +wss.on('connection', (ws, req) => { + const robotId = req.url.split('/')[2]; // /robot/{robotId} + + if (!robotId) { + ws.close(); + return; + } + + console.log(`Serial connection established for robot ${robotId}`); + robotManager.registerSerialConnection(robotId, ws); + + // 시리얼 데이터 수신 처리 + ws.on('message', (message) => { + try { + const data = JSON.parse(message); + if (data.type === 'serial') { + // 시리얼 데이터를 Python 프로세스로 전달 + robotManager.sendCommand(robotId, { type: 'serial', data: data.data }); + } + } catch (error) { + console.error(`Error processing message from robot ${robotId}:`, error); + } + }); + + ws.on('close', () => { + console.log(`Serial connection closed for robot ${robotId}`); + robotManager.removeSerialConnection(robotId); + }); +}); + +// REST API 엔드포인트 +app.post('/api/robots/:robotId/command', (req, res) => { + const { robotId } = req.params; + const command = req.body; + + if (robotManager.sendCommand(robotId, command)) { + res.json({ success: true }); + } else { + res.status(404).json({ error: 'Robot not connected' }); + } +}); + +const PORT = process.env.PORT || 3000; +server.listen(PORT, () => { + console.log(`Server running on port ${PORT}`); +}); + +``` + +```python +# robot_controller.py +import sys +import json +import asyncio +from time import sleep + +class RobotController: + def __init__(self): + self.command_queue = asyncio.Queue() + self.serial_data = None + + async def process_command(self, command): + try: + cmd_type = command.get('type') + + if cmd_type == 'serial': + # 시리얼 데이터 저장 + self.serial_data = command.get('data') + return {'status': 'success', 'type': 'serial_stored'} + + if cmd_type == 'move': + # 시리얼 연결을 통해 로봇으로 명령 전송 + if self.serial_data: + # 실제로는 여기서 시리얼 데이터를 사용하여 로봇과 통신 + params = command.get('params', {}) + return { + 'status': 'success', + 'command': cmd_type, + 'params': params + } + else: + return {'status': 'error', 'message': 'No serial connection'} + + return {'status': 'error', 'message': 'Unknown command'} + + except Exception as e: + return {'status': 'error', 'message': str(e)} + + async def run(self): + while True: + try: + line = await self.get_input() + if not line: + continue + + command = json.loads(line) + result = await self.process_command(command) + + print(json.dumps(result)) + sys.stdout.flush() + + except Exception as e: + print(json.dumps({'status': 'error', 'message': str(e)})) + sys.stdout.flush() + + async def get_input(self): + return await asyncio.get_event_loop().run_in_executor(None, sys.stdin.readline) + +if __name__ == '__main__': + controller = RobotController() + asyncio.get_event_loop().run_until_complete(controller.run()) + +``` + +```javascript +// web-client/serial-client.js +class DobotSerialClient { + constructor(serverUrl) { + this.serverUrl = serverUrl; + this.port = null; + this.reader = null; + this.writer = null; + this.ws = null; + this.robotId = null; + } + + async connect(robotId) { + this.robotId = robotId; + + // 웹시리얼 연결 + try { + this.port = await navigator.serial.requestPort(); + await this.port.open({ baudRate: 115200 }); + + this.reader = this.port.readable.getReader(); + this.writer = this.port.writable.getWriter(); + + // 서버와 웹소켓 연결 + this.ws = new WebSocket(`${this.serverUrl}/robot/${robotId}`); + + // 시리얼 데이터 읽기 시작 + this.startReading(); + + return true; + } catch (error) { + console.error('Connection failed:', error); + return false; + } + } + + async startReading() { + while (true) { + try { + const { value, done } = await this.reader.read(); + if (done) { + break; + } + // 시리얼 데이터를 서버로 전송 + if (this.ws && this.ws.readyState === WebSocket.OPEN) { + this.ws.send(JSON.stringify({ + type: 'serial', + data: Array.from(value) + })); + } + } catch (error) { + console.error('Error reading serial:', error); + break; + } + } + } + + async writeToSerial(data) { + if (this.writer) { + await this.writer.write(new Uint8Array(data)); + } + } + + async disconnect() { + if (this.reader) { + await this.reader.cancel(); + this.reader = null; + } + if (this.writer) { + await this.writer.close(); + this.writer = null; + } + if (this.port) { + await this.port.close(); + this.port = null; + } + if (this.ws) { + this.ws.close(); + this.ws = null; + } + } + + // Blockly 명령어 실행 + async executeBlocklyCommand(blocklyCmd) { + const command = this.translateBlocklyCommand(blocklyCmd); + if (!command) return; + + try { + const response = await fetch( + `${this.serverUrl}/api/robots/${this.robotId}/command`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(command), + } + ); + + if (!response.ok) { + throw new Error('Command failed'); + } + + return await response.json(); + } catch (error) { + console.error('Failed to execute command:', error); + throw error; + } + } + + translateBlocklyCommand(blocklyCmd) { + const commandMap = { + 'move_forward': { type: 'move', params: { x: 10, y: 0, z: 0 } }, + 'move_backward': { type: 'move', params: { x: -10, y: 0, z: 0 } }, + 'grip_open': { type: 'grip', params: { grip: false } }, + 'grip_close': { type: 'grip', params: { grip: true } }, + }; + + return commandMap[blocklyCmd] || null; + } +} + +``` + +이 구현의 주요 특징은 다음과 같습니다: + +1. **중앙 서버에서 실행되는 컴포넌트**: + - Node.js 서버 + - Python 컨트롤러 + - 로봇 관리자 + +2. **클라이언트에서 실행되는 컴포넌트**: + - Web Serial API를 사용한 시리얼 통신 + - WebSocket 클라이언트 + +작동 방식: + +1. 브라우저에서 Web Serial API를 통해 로봇과 시리얼 연결 +2. 시리얼 연결 정보를 WebSocket을 통해 서버로 전송 +3. 서버는 해당 로봇을 위한 Python 프로세스 시작 +4. Blockly 명령어는 서버의 REST API를 통해 전송 +5. 서버의 Python 프로세스가 명령어를 처리하고 시리얼 데이터를 통해 로봇 제어 + +사용 방법: + +1. 서버 설정: +```bash +# 서버 설치 +npm install express ws cors + +# Python 환경 설정 +pip install pyserial + +# 서버 실행 +node index.js +``` + +2. 클라이언트 연결: +```html + + +``` + +이 방식의 장점: +1. 모든 로직이 서버에서 실행되어 관리가 용이 +2. 클라이언트는 시리얼 통신만 담당 +3. 여러 로봇을 중앙에서 제어 가능 +4. 업데이트와 유지보수가 쉬움 + +단점: +1. 서버 부하가 증가할 수 있음 +2. 네트워크 지연이 발생할 수 있음 +3. 서버 장애 시 전체 시스템 영향 + +실제 구현 시 고려사항: +1. 에러 처리 강화 +2. 재연결 로직 추가 +3. 로깅 시스템 구현 +4. 보안 설정 추가 +5. 모니터링 시스템 구축 + +이 방식으로 구현하면 대부분의 로직을 서버에서 처리하면서도, Web Serial API를 통해 로봇과의 직접 통신이 가능합니다. \ No newline at end of file diff --git a/dobot-serial/main/src/logger.ts b/dobot-serial/main/src/logger.ts new file mode 100644 index 0000000..f90047e --- /dev/null +++ b/dobot-serial/main/src/logger.ts @@ -0,0 +1 @@ +export const logger = console diff --git a/dobot-serial/main/src/theme/ThemeRegistry.tsx b/dobot-serial/main/src/theme/ThemeRegistry.tsx new file mode 100644 index 0000000..0003b7d --- /dev/null +++ b/dobot-serial/main/src/theme/ThemeRegistry.tsx @@ -0,0 +1,18 @@ +'use client' + +import * as React from 'react' +import { ThemeProvider } from '@mui/material/styles' +import CssBaseline from '@mui/material/CssBaseline' +import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter' +import theme from './theme' + +export default function ThemeRegistry({ children }: { children: React.ReactNode }) { + return ( + + + + {children} + + + ) +} diff --git a/dobot-serial/main/src/theme/theme.ts b/dobot-serial/main/src/theme/theme.ts new file mode 100644 index 0000000..91aef6c --- /dev/null +++ b/dobot-serial/main/src/theme/theme.ts @@ -0,0 +1,20 @@ +import { createTheme } from '@mui/material/styles' + +const theme = createTheme({ + palette: { + mode: 'light', + }, + components: { + MuiAlert: { + styleOverrides: { + root: ({ ownerState }) => ({ + ...(ownerState.severity === 'info' && { + backgroundColor: '#60a5fa', + }), + }), + }, + }, + }, +}) + +export default theme diff --git a/dobot-serial/main/src/util/gen-id.ts b/dobot-serial/main/src/util/gen-id.ts new file mode 100644 index 0000000..b48fb84 --- /dev/null +++ b/dobot-serial/main/src/util/gen-id.ts @@ -0,0 +1,5 @@ +let seq = 1 + +export function genId(): string { + return (seq++).toString(36).replace('-', '_') +} diff --git a/dobot-serial/main/src/util/misc.ts b/dobot-serial/main/src/util/misc.ts new file mode 100644 index 0000000..662bace --- /dev/null +++ b/dobot-serial/main/src/util/misc.ts @@ -0,0 +1,43 @@ +export function sleepAsync(ms: number): Promise { + return new Promise((resolve) => { + setTimeout(resolve, ms) + }) +} + +export function errmsg(err: any): string { + if (!err) return 'unknown' + if (typeof err === 'string') return err + if (typeof err['message'] === 'string') { + return err['message'] + } + return err.toString() +} + +export function arrayIndexOf(src: Uint8Array, needle: Uint8Array): number { + const needleLen = needle.length + if (src.length < needleLen) return -1 + for (let i = 0; i < src.length - needleLen + 1; i++) { + let found = true + for (let k = 0; k < needle.length; k++) { + if (src[i + k] !== needle[k]) { + found = false + break + } + } + if (found) { + return i + } + } + return -1 +} + +export function arrayConcat(arr1: Uint8Array, arr2: Uint8Array): Uint8Array { + const result = new Uint8Array(arr1.length + arr2.length) + result.set(arr1) + result.set(arr2, arr1.length) + return result +} + +export function chr(ch: string): number { + return ch.charCodeAt(0) +} diff --git a/dobot-serial/main/tsconfig.json b/dobot-serial/main/tsconfig.json new file mode 100644 index 0000000..5c394bc --- /dev/null +++ b/dobot-serial/main/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "@repo/typescript-config/nextjs.json", + "compilerOptions": { + "plugins": [ + { + "name": "next", + }, + ], + "baseUrl": ".", + "paths": { + "@/*": ["src/*"], + }, + "noImplicitAny": false, + // 아래 문제를 해결하기 위해 declaration:false로 설정 + // The inferred type of 'X' cannot be named without a reference + "declaration": false, + "declarationMap": false, + }, + "include": ["next-env.d.ts", "next.config.js", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"], +} diff --git a/dobot-serial/package-lock.json b/dobot-serial/package-lock.json new file mode 100644 index 0000000..e320e8f --- /dev/null +++ b/dobot-serial/package-lock.json @@ -0,0 +1,898 @@ +{ + "name": "codiny-hw-marty", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.4", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "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==", + "dev": true + } + } + }, + "@eslint/js": { + "version": "8.56.0", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "@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==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@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==", + "dev": true + }, + "@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==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@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==", + "dev": true + }, + "acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cmake": { + "version": "0.0.4" + }, + "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==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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==", + "dev": true + }, + "dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "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==", + "dev": true + }, + "eslint": { + "version": "8.56.0", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@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" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "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==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "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==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "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==", + "dev": true + }, + "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==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "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==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "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==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "formidable": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", + "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==", + "requires": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "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" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==" + }, + "ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "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==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "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==", + "dev": true + }, + "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==", + "dev": true + }, + "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==", + "dev": true + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "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==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "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==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "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==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "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==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "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==", + "dev": true + }, + "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==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "3.2.5", + "dev": true + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "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==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "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==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "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==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "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==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "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==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "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==", + "dev": true + }, + "@next/swc-darwin-arm64": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz", + "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==", + "optional": true + }, + "@next/swc-darwin-x64": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz", + "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==", + "optional": true + }, + "@next/swc-linux-arm64-gnu": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz", + "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==", + "optional": true + }, + "@next/swc-linux-arm64-musl": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz", + "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==", + "optional": true + }, + "@next/swc-linux-x64-gnu": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz", + "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==", + "optional": true + }, + "@next/swc-linux-x64-musl": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz", + "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==", + "optional": true + }, + "@next/swc-win32-arm64-msvc": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz", + "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==", + "optional": true + }, + "@next/swc-win32-ia32-msvc": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz", + "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==", + "optional": true + }, + "@next/swc-win32-x64-msvc": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz", + "integrity": "sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==", + "optional": true + } + } +} diff --git a/dobot-serial/package.json b/dobot-serial/package.json new file mode 100644 index 0000000..c90d42a --- /dev/null +++ b/dobot-serial/package.json @@ -0,0 +1,18 @@ +{ + "name": "huenit-serial", + "private": true, + "scripts": { + "build": "turbo build", + "dev": "turbo dev", + "lint": "turbo lint", + "format": "prettier --write \"**/*.{js,jsx,ts,tsx,md}\"" + }, + "devDependencies": { + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "eslint": "^8.57.0", + "prettier": "^3.2.5", + "turbo": "^1.13.3" + }, + "packageManager": "pnpm@8.15.4" +} diff --git a/dobot-serial/pnpm-lock.yaml b/dobot-serial/pnpm-lock.yaml new file mode 100644 index 0000000..51b936d --- /dev/null +++ b/dobot-serial/pnpm-lock.yaml @@ -0,0 +1,4088 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@repo/eslint-config': + specifier: workspace:* + version: link:sub/eslint-config + '@repo/typescript-config': + specifier: workspace:* + version: link:sub/typescript-config + eslint: + specifier: ^8.57.0 + version: 8.57.0 + prettier: + specifier: ^3.2.5 + version: 3.2.5 + turbo: + specifier: ^1.13.3 + version: 1.13.3 + + main: + dependencies: + '@emotion/cache': + specifier: ^11.11.0 + version: 11.11.0 + '@emotion/react': + specifier: ^11.11.1 + version: 11.11.4(@types/react@18.3.2)(react@18.3.1) + '@emotion/styled': + specifier: ^11.11.0 + version: 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.2)(react@18.3.1) + '@ktaicoder/hw-pet': + specifier: ^1.2.9 + version: 1.2.9 + '@mui/material': + specifier: ^5.15.17 + version: 5.15.17(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@mui/material-nextjs': + specifier: ^5.15.11 + version: 5.15.11(@emotion/cache@11.11.0)(@mui/material@5.15.17)(@types/react@18.3.2)(next@14.2.3)(react@18.3.1) + clsx: + specifier: ^2.0.0 + version: 2.1.1 + eventemitter3: + specifier: ^5.0.1 + version: 5.0.1 + next: + specifier: ^14.2.3 + version: 14.2.3(react-dom@18.3.1)(react@18.3.1) + react: + specifier: ^18.3.1 + version: 18.3.1 + react-dom: + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) + rxjs: + specifier: ^7.8.1 + version: 7.8.1 + devDependencies: + '@next/eslint-plugin-next': + specifier: ^14.2.3 + version: 14.2.3 + '@repo/eslint-config': + specifier: workspace:* + version: link:../sub/eslint-config + '@repo/typescript-config': + specifier: workspace:* + version: link:../sub/typescript-config + '@repo/ui': + specifier: workspace:* + version: link:../sub/ui + '@types/node': + specifier: ^17.0.12 + version: 17.0.45 + '@types/react': + specifier: ^18.3.2 + version: 18.3.2 + '@types/react-dom': + specifier: ^18.3.0 + version: 18.3.0 + '@types/w3c-web-serial': + specifier: ^1.0.6 + version: 1.0.6 + '@types/web-bluetooth': + specifier: ^0.0.20 + version: 0.0.20 + typescript: + specifier: ^5.3.3 + version: 5.4.5 + + sub/eslint-config: + devDependencies: + '@typescript-eslint/eslint-plugin': + specifier: ^6.17.0 + version: 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': + specifier: ^6.17.0 + version: 6.21.0(eslint@8.57.0)(typescript@5.4.5) + '@vercel/style-guide': + specifier: ^5.1.0 + version: 5.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.4.5) + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.57.0) + eslint-config-turbo: + specifier: ^1.11.3 + version: 1.13.3(eslint@8.57.0) + eslint-plugin-only-warn: + specifier: ^1.1.0 + version: 1.1.0 + typescript: + specifier: ^5.3.3 + version: 5.4.5 + + sub/typescript-config: {} + + sub/ui: + devDependencies: + '@ktaicoder/hw-pet': + specifier: ^1.2.9 + version: 1.2.9 + '@mui/icons-material': + specifier: ^5.15.17 + version: 5.15.17(@mui/material@5.15.17)(@types/react@18.3.2)(react@18.3.1) + '@mui/material': + specifier: ^5.15.17 + version: 5.15.17(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@repo/eslint-config': + specifier: workspace:* + version: link:../eslint-config + '@repo/typescript-config': + specifier: workspace:* + version: link:../typescript-config + '@types/eslint': + specifier: ^8.44.7 + version: 8.56.10 + '@types/node': + specifier: ^18.19.0 + version: 18.19.33 + '@types/react': + specifier: ^18.3.2 + version: 18.3.2 + '@types/react-dom': + specifier: ^18.3.0 + version: 18.3.0 + clsx: + specifier: ^2.1.0 + version: 2.1.1 + eslint: + specifier: ^8.57.0 + version: 8.57.0 + next: + specifier: ^14.2.3 + version: 14.2.3(react-dom@18.3.1)(react@18.3.1) + react: + specifier: ^18.3.1 + version: 18.3.1 + typescript: + specifier: ^5.3.3 + version: 5.4.5 + +packages: + + /@ampproject/remapping@2.3.0: + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + dev: true + + /@babel/code-frame@7.24.2: + resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.24.5 + picocolors: 1.0.0 + + /@babel/compat-data@7.24.4: + resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.24.5: + resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.5 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) + '@babel/helpers': 7.24.5 + '@babel/parser': 7.24.5 + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.5 + '@babel/types': 7.24.5 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/eslint-parser@7.24.5(@babel/core@7.24.5)(eslint@8.57.0): + resolution: {integrity: sha512-gsUcqS/fPlgAw1kOtpss7uhY6E9SFFANQ6EFX5GTvzUwaV0+sGaZWk6xq22MOdeT9wfxyokW3ceCUvOiRtZciQ==} + 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 + dependencies: + '@babel/core': 7.24.5 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 + eslint: 8.57.0 + eslint-visitor-keys: 2.1.0 + semver: 6.3.1 + dev: true + + /@babel/generator@7.24.5: + resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.5 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + dev: true + + /@babel/helper-compilation-targets@7.23.6: + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.24.4 + '@babel/helper-validator-option': 7.23.5 + browserslist: 4.23.0 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.24.0 + '@babel/types': 7.24.5 + dev: true + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.5 + dev: true + + /@babel/helper-module-imports@7.24.3: + resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.5 + + /@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5): + resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.24.3 + '@babel/helper-simple-access': 7.24.5 + '@babel/helper-split-export-declaration': 7.24.5 + '@babel/helper-validator-identifier': 7.24.5 + dev: true + + /@babel/helper-simple-access@7.24.5: + resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.5 + dev: true + + /@babel/helper-split-export-declaration@7.24.5: + resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.5 + dev: true + + /@babel/helper-string-parser@7.24.1: + resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-identifier@7.24.5: + resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-option@7.23.5: + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers@7.24.5: + resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.5 + '@babel/types': 7.24.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight@7.24.5: + resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.24.5 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.0 + + /@babel/parser@7.24.5: + resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.24.5 + dev: true + + /@babel/runtime@7.24.5: + resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + + /@babel/template@7.24.0: + resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.24.2 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 + dev: true + + /@babel/traverse@7.24.5: + resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.24.5 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.5 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.24.5: + resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.24.1 + '@babel/helper-validator-identifier': 7.24.5 + to-fast-properties: 2.0.0 + + /@emotion/babel-plugin@11.11.0: + resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} + dependencies: + '@babel/helper-module-imports': 7.24.3 + '@babel/runtime': 7.24.5 + '@emotion/hash': 0.9.1 + '@emotion/memoize': 0.8.1 + '@emotion/serialize': 1.1.4 + babel-plugin-macros: 3.1.0 + convert-source-map: 1.9.0 + escape-string-regexp: 4.0.0 + find-root: 1.1.0 + source-map: 0.5.7 + stylis: 4.2.0 + + /@emotion/cache@11.11.0: + resolution: {integrity: sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==} + dependencies: + '@emotion/memoize': 0.8.1 + '@emotion/sheet': 1.2.2 + '@emotion/utils': 1.2.1 + '@emotion/weak-memoize': 0.3.1 + stylis: 4.2.0 + + /@emotion/hash@0.9.1: + resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} + + /@emotion/is-prop-valid@1.2.2: + resolution: {integrity: sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==} + dependencies: + '@emotion/memoize': 0.8.1 + + /@emotion/memoize@0.8.1: + resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} + + /@emotion/react@11.11.4(@types/react@18.3.2)(react@18.3.1): + resolution: {integrity: sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==} + peerDependencies: + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.5 + '@emotion/babel-plugin': 11.11.0 + '@emotion/cache': 11.11.0 + '@emotion/serialize': 1.1.4 + '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.3.1) + '@emotion/utils': 1.2.1 + '@emotion/weak-memoize': 0.3.1 + '@types/react': 18.3.2 + hoist-non-react-statics: 3.3.2 + react: 18.3.1 + + /@emotion/serialize@1.1.4: + resolution: {integrity: sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==} + dependencies: + '@emotion/hash': 0.9.1 + '@emotion/memoize': 0.8.1 + '@emotion/unitless': 0.8.1 + '@emotion/utils': 1.2.1 + csstype: 3.1.3 + + /@emotion/sheet@1.2.2: + resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} + + /@emotion/styled@11.11.5(@emotion/react@11.11.4)(@types/react@18.3.2)(react@18.3.1): + resolution: {integrity: sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==} + peerDependencies: + '@emotion/react': ^11.0.0-rc.0 + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.5 + '@emotion/babel-plugin': 11.11.0 + '@emotion/is-prop-valid': 1.2.2 + '@emotion/react': 11.11.4(@types/react@18.3.2)(react@18.3.1) + '@emotion/serialize': 1.1.4 + '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.3.1) + '@emotion/utils': 1.2.1 + '@types/react': 18.3.2 + react: 18.3.1 + + /@emotion/unitless@0.8.1: + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + + /@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@18.3.1): + resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==} + peerDependencies: + react: '>=16.8.0' + dependencies: + react: 18.3.1 + + /@emotion/utils@1.2.1: + resolution: {integrity: sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==} + + /@emotion/weak-memoize@0.3.1: + resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} + + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.57.0: + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@floating-ui/core@1.6.1: + resolution: {integrity: sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A==} + dependencies: + '@floating-ui/utils': 0.2.2 + + /@floating-ui/dom@1.6.5: + resolution: {integrity: sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==} + dependencies: + '@floating-ui/core': 1.6.1 + '@floating-ui/utils': 0.2.2 + + /@floating-ui/react-dom@2.0.9(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.6.5 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + /@floating-ui/utils@0.2.2: + resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==} + + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.3: + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + dev: true + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true + + /@jridgewell/gen-mapping@0.3.5: + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + dev: true + + /@jridgewell/resolve-uri@3.1.2: + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.2.1: + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.25: + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@ktaicoder/hw-pet@1.2.9: + resolution: {integrity: sha512-eRFRvMtp7fIAIDGSvUq8hAor1ojRPYlgHrvHlY+g6JOR4LpY3IElspuB8FZQ5JZbov8oHzaLltCbCwTmhC3wPQ==} + dependencies: + eventemitter3: 5.0.1 + + /@microsoft/tsdoc-config@0.16.2: + resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + dev: true + + /@microsoft/tsdoc@0.14.2: + resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + dev: true + + /@mui/base@5.0.0-beta.40(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.5 + '@floating-ui/react-dom': 2.0.9(react-dom@18.3.1)(react@18.3.1) + '@mui/types': 7.2.14(@types/react@18.3.2) + '@mui/utils': 5.15.14(@types/react@18.3.2)(react@18.3.1) + '@popperjs/core': 2.11.8 + '@types/react': 18.3.2 + clsx: 2.1.1 + prop-types: 15.8.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + /@mui/core-downloads-tracker@5.15.17: + resolution: {integrity: sha512-DVAejDQkjNnIac7MfP8sLzuo7fyrBPxNdXe+6bYqOqg1z2OPTlfFAejSNzWe7UenRMuFu9/AyFXj/X2vN2w6dA==} + + /@mui/icons-material@5.15.17(@mui/material@5.15.17)(@types/react@18.3.2)(react@18.3.1): + resolution: {integrity: sha512-xVzl2De7IY36s/keHX45YMiCpsIx3mNv2xwDgtBkRSnZQtVk+Gqufwj1ktUxEyjzEhBl0+PiNJqYC31C+n1n6A==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@mui/material': ^5.0.0 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.5 + '@mui/material': 5.15.17(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@types/react': 18.3.2 + react: 18.3.1 + dev: true + + /@mui/material-nextjs@5.15.11(@emotion/cache@11.11.0)(@mui/material@5.15.17)(@types/react@18.3.2)(next@14.2.3)(react@18.3.1): + resolution: {integrity: sha512-cp5RWYbBngyi7NKP91R9QITllfxumCVPFjqe4AKzNROVuCot0VpgkafxXqfbv0uFsyUU0ROs0O2M3r17q604Aw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/cache': ^11.11.0 + '@emotion/server': ^11.11.0 + '@mui/material': ^5.0.0 + '@types/react': ^17.0.0 || ^18.0.0 + next: ^13.0.0 || ^14.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/cache': + optional: true + '@emotion/server': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.5 + '@emotion/cache': 11.11.0 + '@mui/material': 5.15.17(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@types/react': 18.3.2 + next: 14.2.3(react-dom@18.3.1)(react@18.3.1) + react: 18.3.1 + dev: false + + /@mui/material@5.15.17(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-ru/MLvTkCh0AZXmqwIpqGTOoVBS/sX48zArXq/DvktxXZx4fskiRA2PEc7Rk5ZlFiZhKh4moL4an+l8zZwq49Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.5 + '@emotion/react': 11.11.4(@types/react@18.3.2)(react@18.3.1) + '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.2)(react@18.3.1) + '@mui/base': 5.0.0-beta.40(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@mui/core-downloads-tracker': 5.15.17 + '@mui/system': 5.15.15(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.2)(react@18.3.1) + '@mui/types': 7.2.14(@types/react@18.3.2) + '@mui/utils': 5.15.14(@types/react@18.3.2)(react@18.3.1) + '@types/react': 18.3.2 + '@types/react-transition-group': 4.4.10 + clsx: 2.1.1 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-is: 18.3.1 + react-transition-group: 4.4.5(react-dom@18.3.1)(react@18.3.1) + + /@mui/private-theming@5.15.14(@types/react@18.3.2)(react@18.3.1): + resolution: {integrity: sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.5 + '@mui/utils': 5.15.14(@types/react@18.3.2)(react@18.3.1) + '@types/react': 18.3.2 + prop-types: 15.8.1 + react: 18.3.1 + + /@mui/styled-engine@5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(react@18.3.1): + resolution: {integrity: sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.4.1 + '@emotion/styled': ^11.3.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + dependencies: + '@babel/runtime': 7.24.5 + '@emotion/cache': 11.11.0 + '@emotion/react': 11.11.4(@types/react@18.3.2)(react@18.3.1) + '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.2)(react@18.3.1) + csstype: 3.1.3 + prop-types: 15.8.1 + react: 18.3.1 + + /@mui/system@5.15.15(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.2)(react@18.3.1): + resolution: {integrity: sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.5 + '@emotion/react': 11.11.4(@types/react@18.3.2)(react@18.3.1) + '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.2)(react@18.3.1) + '@mui/private-theming': 5.15.14(@types/react@18.3.2)(react@18.3.1) + '@mui/styled-engine': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(react@18.3.1) + '@mui/types': 7.2.14(@types/react@18.3.2) + '@mui/utils': 5.15.14(@types/react@18.3.2)(react@18.3.1) + '@types/react': 18.3.2 + clsx: 2.1.1 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 18.3.1 + + /@mui/types@7.2.14(@types/react@18.3.2): + resolution: {integrity: sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.3.2 + + /@mui/utils@5.15.14(@types/react@18.3.2)(react@18.3.1): + resolution: {integrity: sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.5 + '@types/prop-types': 15.7.12 + '@types/react': 18.3.2 + prop-types: 15.8.1 + react: 18.3.1 + react-is: 18.3.1 + + /@next/env@14.2.3: + resolution: {integrity: sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==} + + /@next/eslint-plugin-next@14.2.3: + resolution: {integrity: sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==} + dependencies: + glob: 10.3.10 + dev: true + + /@next/swc-darwin-arm64@14.2.3: + resolution: {integrity: sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@next/swc-darwin-x64@14.2.3: + resolution: {integrity: sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@next/swc-linux-arm64-gnu@14.2.3: + resolution: {integrity: sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@next/swc-linux-arm64-musl@14.2.3: + resolution: {integrity: sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@next/swc-linux-x64-gnu@14.2.3: + resolution: {integrity: sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@next/swc-linux-x64-musl@14.2.3: + resolution: {integrity: sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@next/swc-win32-arm64-msvc@14.2.3: + resolution: {integrity: sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + /@next/swc-win32-ia32-msvc@14.2.3: + resolution: {integrity: sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + /@next/swc-win32-x64-msvc@14.2.3: + resolution: {integrity: sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + dependencies: + eslint-scope: 5.1.1 + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + dev: true + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: true + optional: true + + /@pkgr/core@0.1.1: + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dev: true + + /@popperjs/core@2.11.8: + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + + /@rushstack/eslint-patch@1.10.2: + resolution: {integrity: sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==} + dev: true + + /@swc/counter@0.1.3: + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + /@swc/helpers@0.5.5: + resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} + dependencies: + '@swc/counter': 0.1.3 + tslib: 2.6.2 + + /@types/eslint@8.56.10: + resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==} + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/node@17.0.45: + resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + dev: true + + /@types/node@18.19.33: + resolution: {integrity: sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/normalize-package-data@2.4.4: + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + dev: true + + /@types/parse-json@4.0.2: + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + + /@types/prop-types@15.7.12: + resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + + /@types/react-dom@18.3.0: + resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} + dependencies: + '@types/react': 18.3.2 + dev: true + + /@types/react-transition-group@4.4.10: + resolution: {integrity: sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==} + dependencies: + '@types/react': 18.3.2 + + /@types/react@18.3.2: + resolution: {integrity: sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==} + dependencies: + '@types/prop-types': 15.7.12 + csstype: 3.1.3 + + /@types/semver@7.5.8: + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + dev: true + + /@types/w3c-web-serial@1.0.6: + resolution: {integrity: sha512-5IlDdQ2C56sCVwc7CUlqT9Axxw+0V/FbWRbErklYIzZ5mKL9s4l7epXHygn+4X7L2nmAPnVvRl55XUVo0760Rg==} + dev: true + + /@types/web-bluetooth@0.0.20: + resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + dev: true + + /@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.4 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + semver: 7.6.2 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.4 + eslint: 8.57.0 + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@5.62.0: + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + dev: true + + /@typescript-eslint/scope-manager@6.21.0: + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + dev: true + + /@typescript-eslint/type-utils@6.21.0(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.5) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + debug: 4.3.4 + eslint: 8.57.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@5.62.0: + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/types@6.21.0: + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.5): + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + 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.6.2 + tsutils: 3.21.0(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@6.21.0(typescript@5.4.5): + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.2 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) + eslint: 8.57.0 + eslint-scope: 5.1.1 + semver: 7.6.2 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.5) + eslint: 8.57.0 + semver: 7.6.2 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@5.62.0: + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@typescript-eslint/visitor-keys@6.21.0: + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /@vercel/style-guide@5.2.0(eslint@8.57.0)(prettier@3.2.5)(typescript@5.4.5): + resolution: {integrity: sha512-fNSKEaZvSkiBoF6XEefs8CcgAV9K9e+MbcsDZjUsktHycKdA0jvjAzQi1W/FzLS+Nr5zZ6oejCwq/97dHUKe0g==} + engines: {node: '>=16'} + peerDependencies: + '@next/eslint-plugin-next': '>=12.3.0 <15' + eslint: '>=8.48.0 <9' + prettier: '>=3.0.0 <4' + typescript: '>=4.8.0 <6' + peerDependenciesMeta: + '@next/eslint-plugin-next': + optional: true + eslint: + optional: true + prettier: + optional: true + typescript: + optional: true + dependencies: + '@babel/core': 7.24.5 + '@babel/eslint-parser': 7.24.5(@babel/core@7.24.5)(eslint@8.57.0) + '@rushstack/eslint-patch': 1.10.2 + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + eslint: 8.57.0 + eslint-config-prettier: 9.1.0(eslint@8.57.0) + eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.29.1) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.4.5) + eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) + eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0) + eslint-plugin-react: 7.34.1(eslint@8.57.0) + eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) + eslint-plugin-testing-library: 6.2.2(eslint@8.57.0)(typescript@5.4.5) + eslint-plugin-tsdoc: 0.2.17 + eslint-plugin-unicorn: 48.0.1(eslint@8.57.0) + prettier: 3.2.5 + prettier-plugin-packagejson: 2.5.0(prettier@3.2.5) + typescript: 5.4.5 + transitivePeerDependencies: + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - jest + - supports-color + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.3): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.3 + dev: true + + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + dependencies: + dequal: 2.0.3 + dev: true + + /array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + dev: true + + /array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + is-string: 1.0.7 + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.toreversed@1.1.2: + resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.tosorted@1.1.3: + resolution: {integrity: sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==} + 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 + dev: true + + /arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + is-array-buffer: 3.0.4 + is-shared-array-buffer: 1.0.3 + dev: true + + /ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + dev: true + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: true + + /axe-core@4.7.0: + resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} + engines: {node: '>=4'} + dev: true + + /axobject-query@3.2.1: + resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + dependencies: + dequal: 2.0.3 + dev: true + + /babel-plugin-macros@3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + dependencies: + '@babel/runtime': 7.24.5 + cosmiconfig: 7.1.0 + resolve: 1.22.8 + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist@4.23.0: + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001617 + electron-to-chromium: 1.4.763 + node-releases: 2.0.14 + update-browserslist-db: 1.0.15(browserslist@4.23.0) + dev: true + + /builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: true + + /busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + dependencies: + streamsearch: 1.1.0 + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + 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.2 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + /caniuse-lite@1.0.30001617: + resolution: {integrity: sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==} + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: true + + /clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + /clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + /damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + dev: true + + /data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + dev: true + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + dev: true + + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: true + + /detect-indent@7.0.1: + resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} + engines: {node: '>=12.20'} + dev: true + + /detect-newline@4.0.1: + resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dom-helpers@5.2.1: + resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dependencies: + '@babel/runtime': 7.24.5 + csstype: 3.1.3 + + /dotenv@16.0.3: + resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} + engines: {node: '>=12'} + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /electron-to-chromium@1.4.763: + resolution: {integrity: sha512-k4J8NrtJ9QrvHLRo8Q18OncqBCB7tIUyqxRcJnlonQ0ioHKYB988GcDFF3ZePmnb8eHEopDs/wPHR/iGAFgoUQ==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /enhanced-resolve@5.16.1: + resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + + /es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + 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.1 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.2 + 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 + dev: true + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + dev: true + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: true + + /es-iterator-helpers@1.0.19: + resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} + engines: {node: '>= 0.4'} + 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 + 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.2 + safe-array-concat: 1.1.2 + dev: true + + /es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + dev: true + + /es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + dev: true + + /es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + dependencies: + hasown: 2.0.2 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + /eslint-config-prettier@9.1.0(eslint@8.57.0): + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.57.0 + dev: true + + /eslint-config-turbo@1.13.3(eslint@8.57.0): + resolution: {integrity: sha512-if/QtwEiWZ5b7Bg8yZBPSvS0TeCG2Zvfa/+XBYANS7uSYucjmW+BBC8enJB0PqpB/YLGGOumeo3x7h1Nuba9iw==} + peerDependencies: + eslint: '>6.6.0' + dependencies: + eslint: 8.57.0 + eslint-plugin-turbo: 1.13.3(eslint@8.57.0) + dev: true + + /eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.29.1): + resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} + engines: {node: '>= 4'} + peerDependencies: + eslint-plugin-import: '>=1.4.0' + dependencies: + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + dev: true + + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0): + resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + dependencies: + debug: 4.3.4 + enhanced-resolve: 5.16.1 + eslint: 8.57.0 + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + fast-glob: 3.3.2 + get-tsconfig: 4.7.5 + is-core-module: 2.13.1 + is-glob: 4.0.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + debug: 3.2.7 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): + resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} + engines: {node: '>=6.5.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + escape-string-regexp: 1.0.5 + eslint: 8.57.0 + ignore: 5.3.1 + dev: true + + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.5) + 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: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + hasown: 2.0.2 + is-core-module: 2.13.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 + tsconfig-paths: 3.15.0 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 || ^7.0.0 + eslint: ^7.0.0 || ^8.0.0 + jest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + jest: + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): + resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + '@babel/runtime': 7.24.5 + aria-query: 5.3.0 + array-includes: 3.1.8 + array.prototype.flatmap: 1.3.2 + ast-types-flow: 0.0.8 + axe-core: 4.7.0 + axobject-query: 3.2.1 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + es-iterator-helpers: 1.0.19 + eslint: 8.57.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + dev: true + + /eslint-plugin-only-warn@1.1.0: + resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} + engines: {node: '>=6'} + dev: true + + /eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0): + resolution: {integrity: sha512-DcHpF0SLbNeh9MT4pMzUGuUSnJ7q5MWbP8sSEFIMS6j7Ggnduq8ghNlfhURgty4c1YFny7Ge9xYTO1FSAoV2Vw==} + peerDependencies: + eslint: '>=7' + eslint-plugin-jest: '>=25' + peerDependenciesMeta: + eslint-plugin-jest: + optional: true + dependencies: + eslint: 8.57.0 + eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.4.5) + dev: true + + /eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): + resolution: {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 + dependencies: + eslint: 8.57.0 + dev: true + + /eslint-plugin-react@7.34.1(eslint@8.57.0): + resolution: {integrity: sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + array-includes: 3.1.8 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.2 + array.prototype.toreversed: 1.1.2 + array.prototype.tosorted: 1.1.3 + doctrine: 2.1.0 + es-iterator-helpers: 1.0.19 + eslint: 8.57.0 + estraverse: 5.3.0 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + object.hasown: 1.1.4 + 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 + dev: true + + /eslint-plugin-testing-library@6.2.2(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-1E94YOTUDnOjSLyvOwmbVDzQi/WkKm3WVrMXu6SmBr6DN95xTGZmI6HJ/eOkSXh/DlheRsxaPsJvZByDBhWLVQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} + peerDependencies: + eslint: ^7.5.0 || ^8.0.0 + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-plugin-tsdoc@0.2.17: + resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + dev: true + + /eslint-plugin-turbo@1.13.3(eslint@8.57.0): + resolution: {integrity: sha512-RjmlnqYsEqnJ+U3M3IS5jLJDjWv5NsvReCpsC61n5pJ4JMHTZ/lU0EIoL1ccuL1L5wP0APzdXdByBxERcPQ+Nw==} + peerDependencies: + eslint: '>6.6.0' + dependencies: + dotenv: 16.0.3 + eslint: 8.57.0 + dev: true + + /eslint-plugin-unicorn@48.0.1(eslint@8.57.0): + resolution: {integrity: sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==} + engines: {node: '>=16'} + peerDependencies: + eslint: '>=8.44.0' + dependencies: + '@babel/helper-validator-identifier': 7.24.5 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + ci-info: 3.9.0 + clean-regexp: 1.0.0 + eslint: 8.57.0 + esquery: 1.5.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.0.2 + lodash: 4.17.21 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.6.2 + strip-indent: 3.0.0 + dev: true + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + 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.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + 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.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 3.4.3 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-root@1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + dev: true + + /get-stdin@9.0.0: + resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} + engines: {node: '>=12'} + dev: true + + /get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + dev: true + + /get-tsconfig@4.7.5: + resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + + /git-hooks-list@3.1.0: + resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.4 + minipass: 7.1.1 + path-scurry: 1.11.1 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + gopd: 1.0.1 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + dev: true + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + + /hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + dependencies: + react-is: 16.13.1 + + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + dev: true + + /is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + /is-async-function@2.0.0: + resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.2 + + /is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + dependencies: + is-typed-array: 1.1.13 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-finalizationregistry@1.0.2: + resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + dev: true + + /is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + dev: true + + /is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.15 + dev: true + + /is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /iterator.prototype@1.1.2: + resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} + dependencies: + define-properties: 1.2.1 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + reflect.getprototypeof: 1.0.6 + set-function-name: 2.0.2 + dev: true + + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: true + + /jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.2 + object.assign: 4.1.5 + object.values: 1.2.0 + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /language-subtag-registry@0.3.22: + resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} + dev: true + + /language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + dependencies: + language-subtag-registry: 0.3.22 + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + + /lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} + engines: {node: 14 || >=16.14} + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /minipass@7.1.1: + resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /next@14.2.3(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==} + engines: {node: '>=18.17.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.41.2 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + sass: + optional: true + dependencies: + '@next/env': 14.2.3 + '@swc/helpers': 0.5.5 + busboy: 1.6.0 + caniuse-lite: 1.0.30001617 + graceful-fs: 4.2.11 + postcss: 8.4.31 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-jsx: 5.1.1(react@18.3.1) + optionalDependencies: + '@next/swc-darwin-arm64': 14.2.3 + '@next/swc-darwin-x64': 14.2.3 + '@next/swc-linux-arm64-gnu': 14.2.3 + '@next/swc-linux-arm64-musl': 14.2.3 + '@next/swc-linux-x64-gnu': 14.2.3 + '@next/swc-linux-x64-musl': 14.2.3 + '@next/swc-win32-arm64-msvc': 14.2.3 + '@next/swc-win32-ia32-msvc': 14.2.3 + '@next/swc-win32-x64-msvc': 14.2.3 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: true + + /normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.8 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.entries@1.1.8: + resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + dev: true + + /object.hasown@1.1.4: + resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /object.values@1.2.0: + resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.24.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + /path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + dependencies: + lru-cache: 10.2.2 + minipass: 7.1.1 + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true + + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: true + + /postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.2.0 + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-plugin-packagejson@2.5.0(prettier@3.2.5): + resolution: {integrity: sha512-6XkH3rpin5QEQodBSVNg+rBo4r91g/1mCaRwS1YGdQJZ6jwqrg2UchBsIG9tpS1yK1kNBvOt84OILsX8uHzBGg==} + peerDependencies: + prettier: '>= 1.16.0' + peerDependenciesMeta: + prettier: + optional: true + dependencies: + prettier: 3.2.5 + sort-package-json: 2.10.0 + synckit: 0.9.0 + dev: true + + /prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /react-dom@18.3.1(react@18.3.1): + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + peerDependencies: + react: ^18.3.1 + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + /react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + /react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + /react-transition-group@4.4.5(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + peerDependencies: + react: '>=16.6.0' + react-dom: '>=16.6.0' + dependencies: + '@babel/runtime': 7.24.5 + dom-helpers: 5.2.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + /react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + + /read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /reflect.getprototypeof@1.0.6: + resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + globalthis: 1.0.4 + which-builtin-type: 1.1.3 + dev: true + + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + /regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + dev: true + + /regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + dev: true + + /regjsparser@0.10.0: + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + + /resolve@1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + /resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + dependencies: + tslib: 2.6.2 + dev: false + + /safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-regex: 1.1.4 + dev: true + + /scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + dependencies: + loose-envify: 1.4.0 + + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + 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 + dev: true + + /set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.1 + dev: true + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: true + + /sort-object-keys@1.1.3: + resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} + dev: true + + /sort-package-json@2.10.0: + resolution: {integrity: sha512-MYecfvObMwJjjJskhxYfuOADkXp1ZMMnCFC8yhp+9HDsk7HhR336hd7eiBs96lTXfiqmUNI+WQCeCMRBhl251g==} + hasBin: true + dependencies: + detect-indent: 7.0.1 + detect-newline: 4.0.1 + get-stdin: 9.0.0 + git-hooks-list: 3.1.0 + globby: 13.2.2 + is-plain-obj: 4.1.0 + semver: 7.6.2 + sort-object-keys: 1.1.3 + dev: true + + /source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + + /source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.17 + dev: true + + /spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.17 + dev: true + + /spdx-license-ids@3.0.17: + resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} + dev: true + + /streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + + /string.prototype.matchall@4.0.11: + resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + 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 + dev: true + + /string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /styled-jsx@5.1.1(react@18.3.1): + resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + dependencies: + client-only: 0.0.1 + react: 18.3.1 + + /stylis@4.2.0: + resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + /synckit@0.9.0: + resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.6.2 + dev: true + + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /ts-api-utils@1.3.0(typescript@5.4.5): + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.4.5 + dev: true + + /tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + /tsutils@3.21.0(typescript@5.4.5): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + 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' + dependencies: + tslib: 1.14.1 + typescript: 5.4.5 + dev: true + + /turbo-darwin-64@1.13.3: + resolution: {integrity: sha512-glup8Qx1qEFB5jerAnXbS8WrL92OKyMmg5Hnd4PleLljAeYmx+cmmnsmLT7tpaVZIN58EAAwu8wHC6kIIqhbWA==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /turbo-darwin-arm64@1.13.3: + resolution: {integrity: sha512-/np2xD+f/+9qY8BVtuOQXRq5f9LehCFxamiQnwdqWm5iZmdjygC5T3uVSYuagVFsZKMvX3ycySwh8dylGTl6lg==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /turbo-linux-64@1.13.3: + resolution: {integrity: sha512-G+HGrau54iAnbXLfl+N/PynqpDwi/uDzb6iM9hXEDG+yJnSJxaHMShhOkXYJPk9offm9prH33Khx2scXrYVW1g==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /turbo-linux-arm64@1.13.3: + resolution: {integrity: sha512-qWwEl5VR02NqRyl68/3pwp3c/olZuSp+vwlwrunuoNTm6JXGLG5pTeme4zoHNnk0qn4cCX7DFrOboArlYxv0wQ==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /turbo-windows-64@1.13.3: + resolution: {integrity: sha512-Nudr4bRChfJzBPzEmpVV85VwUYRCGKecwkBFpbp2a4NtrJ3+UP1VZES653ckqCu2FRyRuS0n03v9euMbAvzH+Q==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /turbo-windows-arm64@1.13.3: + resolution: {integrity: sha512-ouJCgsVLd3icjRLmRvHQDDZnmGzT64GBupM1Y+TjtYn2LVaEBoV6hicFy8x5DUpnqdLy+YpCzRMkWlwhmkX7sQ==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /turbo@1.13.3: + resolution: {integrity: sha512-n17HJv4F4CpsYTvKzUJhLbyewbXjq1oLCi90i5tW1TiWDz16ML1eDG7wi5dHaKxzh5efIM56SITnuVbMq5dk4g==} + hasBin: true + optionalDependencies: + turbo-darwin-64: 1.13.3 + turbo-darwin-arm64: 1.13.3 + turbo-linux-64: 1.13.3 + turbo-linux-arm64: 1.13.3 + turbo-windows-64: 1.13.3 + turbo-windows-arm64: 1.13.3 + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-typed-array: 1.1.13 + dev: true + + /typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + 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 + dev: true + + /typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + 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 + dev: true + + /typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + 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 + possible-typed-array-names: 1.0.0 + dev: true + + /typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.7 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /update-browserslist-db@1.0.15(browserslist@4.23.0): + resolution: {integrity: sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.23.0 + escalade: 3.1.2 + picocolors: 1.0.0 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-builtin-type@1.1.3: + resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} + engines: {node: '>= 0.4'} + 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 + dev: true + + /which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + dev: true + + /which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + 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 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/dobot-serial/pnpm-workspace.yaml b/dobot-serial/pnpm-workspace.yaml new file mode 100644 index 0000000..446f46b --- /dev/null +++ b/dobot-serial/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - "main" + - "sub/*" diff --git a/dobot-serial/sub/eslint-config/README.md b/dobot-serial/sub/eslint-config/README.md new file mode 100644 index 0000000..8b42d90 --- /dev/null +++ b/dobot-serial/sub/eslint-config/README.md @@ -0,0 +1,3 @@ +# `@turbo/eslint-config` + +Collection of internal eslint configurations. diff --git a/dobot-serial/sub/eslint-config/library.js b/dobot-serial/sub/eslint-config/library.js new file mode 100644 index 0000000..09e6052 --- /dev/null +++ b/dobot-serial/sub/eslint-config/library.js @@ -0,0 +1,59 @@ +const { resolve } = require('node:path') + +const project = resolve(process.cwd(), 'tsconfig.json') + +console.log('tsconfig.json location:', project) +/** @type {import("eslint").Linter.Config} */ +module.exports = { + extends: [ + 'eslint:recommended', + 'prettier', + require.resolve('@vercel/style-guide/eslint/typescript'), + 'eslint-config-turbo', + ], + globals: { + React: true, + JSX: true, + }, + env: { + node: true, + }, + plugins: ['only-warn', '@typescript-eslint'], + settings: { + 'import/resolver': { + typescript: { + project, + }, + }, + }, + ignorePatterns: [ + // Ignore dotfiles + '.*.js', + 'node_modules/', + 'dist/', + ], + overrides: [ + { + files: ['*.js?(x)', '*.ts?(x)'], + }, + ], + rules: { + 'no-unused-vars': 'off', + 'no-new-func': 'off', + 'func-names': 'off', + 'no-console': 'off', + 'no-undef': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/consistent-type-imports': [ + 'warn', + { + prefer: 'type-imports', + disallowTypeAnnotations: true, + fixStyle: 'separate-type-imports', + }, + ], + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-shadow': 'off', + }, +} diff --git a/dobot-serial/sub/eslint-config/next.js b/dobot-serial/sub/eslint-config/next.js new file mode 100644 index 0000000..d637f75 --- /dev/null +++ b/dobot-serial/sub/eslint-config/next.js @@ -0,0 +1,55 @@ +const { resolve } = require('node:path') + +const project = resolve(process.cwd(), 'tsconfig.json') + +/** @type {import("eslint").Linter.Config} */ +module.exports = { + extends: [ + 'eslint:recommended', + 'prettier', + require.resolve('@vercel/style-guide/eslint/react'), + require.resolve('@vercel/style-guide/eslint/next'), + 'eslint-config-turbo', + ], + globals: { + React: true, + JSX: true, + }, + env: { + node: true, + browser: true, + }, + plugins: ['only-warn', '@typescript-eslint'], + settings: { + 'import/resolver': { + typescript: { + project, + }, + }, + }, + ignorePatterns: [ + // Ignore dotfiles + '.*.js', + 'node_modules/', + ], + overrides: [{ files: ['*.js?(x)', '*.ts?(x)'] }], + rules: { + 'no-unused-vars': 'off', + 'no-new-func': 'off', + 'func-names': 'off', + 'no-console': 'off', + 'no-undef': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/consistent-type-imports': [ + 'warn', + { + prefer: 'type-imports', + disallowTypeAnnotations: true, + fixStyle: 'separate-type-imports', + }, + ], + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-shadow': 'off', + }, +} diff --git a/dobot-serial/sub/eslint-config/package.json b/dobot-serial/sub/eslint-config/package.json new file mode 100644 index 0000000..b2b1b26 --- /dev/null +++ b/dobot-serial/sub/eslint-config/package.json @@ -0,0 +1,19 @@ +{ + "name": "@repo/eslint-config", + "version": "0.0.0", + "private": true, + "files": [ + "library.js", + "next.js", + "react-internal.js" + ], + "devDependencies": { + "@vercel/style-guide": "^5.1.0", + "eslint-config-turbo": "^1.11.3", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-only-warn": "^1.1.0", + "@typescript-eslint/parser": "^6.17.0", + "@typescript-eslint/eslint-plugin": "^6.17.0", + "typescript": "^5.3.3" + } +} \ No newline at end of file diff --git a/dobot-serial/sub/eslint-config/react-internal.js b/dobot-serial/sub/eslint-config/react-internal.js new file mode 100644 index 0000000..f47c84e --- /dev/null +++ b/dobot-serial/sub/eslint-config/react-internal.js @@ -0,0 +1,77 @@ +const { resolve } = require('node:path') + +const project = resolve(process.cwd(), 'tsconfig.json') + +/* + * This is a custom ESLint configuration for use with + * internal (bundled by their consumer) libraries + * that utilize React. + * + * This config extends the Vercel Engineering Style Guide. + * For more information, see https://github.com/vercel/style-guide + * + */ + +/** @type {import("eslint").Linter.Config} */ +module.exports = { + extends: [ + 'eslint:recommended', + 'prettier', + require.resolve('@vercel/style-guide/eslint/react'), + require.resolve('@vercel/style-guide/eslint/typescript'), + 'eslint-config-turbo', + ], + plugins: ['only-warn', '@typescript-eslint'], + globals: { + React: true, + JSX: true, + }, + env: { + browser: true, + }, + settings: { + 'import/resolver': { + typescript: { + project, + }, + }, + }, + ignorePatterns: [ + // Ignore dotfiles + '.*.js', + 'node_modules/', + 'dist/', + ], + overrides: [ + // Force ESLint to detect .tsx files + { files: ['*.js?(x)', '*.ts?(x)'] }, + ], + rules: { + 'no-unused-vars': 'off', + 'no-new-func': 'off', + 'func-names': 'off', + 'no-console': 'off', + 'no-undef': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/consistent-type-imports': [ + 'warn', + { + prefer: 'type-imports', + disallowTypeAnnotations: true, + fixStyle: 'separate-type-imports', + }, + ], + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-unnecessary-condition': 'off', + '@typescript-eslint/no-floating-promises': 'off', + '@typescript-eslint/naming-convention': 'off', + 'turbo/no-undeclared-env-vars': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-shadow': 'off', + 'react/jsx-sort-props': 'off', + }, +} diff --git a/dobot-serial/sub/typescript-config/base.json b/dobot-serial/sub/typescript-config/base.json new file mode 100644 index 0000000..b9e6ed6 --- /dev/null +++ b/dobot-serial/sub/typescript-config/base.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Default", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "esModuleInterop": true, + "incremental": false, + "isolatedModules": true, + "lib": [ + "es2022", + "DOM", + "DOM.Iterable" + ], + "module": "NodeNext", + "moduleDetection": "force", + "moduleResolution": "NodeNext", + "noUncheckedIndexedAccess": false, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "strictNullChecks": true, + "target": "ES2022" + } +} diff --git a/dobot-serial/sub/typescript-config/nextjs.json b/dobot-serial/sub/typescript-config/nextjs.json new file mode 100644 index 0000000..44f4289 --- /dev/null +++ b/dobot-serial/sub/typescript-config/nextjs.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Next.js", + "extends": "./base.json", + "compilerOptions": { + "plugins": [{ "name": "next" }], + "module": "ESNext", + "moduleResolution": "Bundler", + "allowJs": true, + "jsx": "preserve", + "noEmit": true + } +} diff --git a/dobot-serial/sub/typescript-config/package.json b/dobot-serial/sub/typescript-config/package.json new file mode 100644 index 0000000..27c0e60 --- /dev/null +++ b/dobot-serial/sub/typescript-config/package.json @@ -0,0 +1,9 @@ +{ + "name": "@repo/typescript-config", + "version": "0.0.0", + "private": true, + "license": "MIT", + "publishConfig": { + "access": "public" + } +} diff --git a/dobot-serial/sub/typescript-config/react-library.json b/dobot-serial/sub/typescript-config/react-library.json new file mode 100644 index 0000000..a755ffe --- /dev/null +++ b/dobot-serial/sub/typescript-config/react-library.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "React Library", + "extends": "./base.json", + "compilerOptions": { + "jsx": "react-jsx", + } +} diff --git a/dobot-serial/sub/typescript-config/vite.json b/dobot-serial/sub/typescript-config/vite.json new file mode 100644 index 0000000..eb9eaff --- /dev/null +++ b/dobot-serial/sub/typescript-config/vite.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./base.json", + "Display": "Vite", + "compilerOptions": { + "allowJs": true, + "esModuleInterop": true, + "jsx": "react", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "module": "ESNext", + "noEmit": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "target": "ESNext", + "types": [ + "vite/client", + "node" + ] + } +} diff --git a/dobot-serial/sub/ui/.eslintrc.cjs b/dobot-serial/sub/ui/.eslintrc.cjs new file mode 100644 index 0000000..e40b1c3 --- /dev/null +++ b/dobot-serial/sub/ui/.eslintrc.cjs @@ -0,0 +1,11 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + root: true, + extends: ['@repo/eslint-config/react-internal.js'], + parser: '@typescript-eslint/parser', + parserOptions: { + project: './tsconfig.json', + sourceType: 'module', + tsconfigRootDir: __dirname, + }, +}; diff --git a/dobot-serial/sub/ui/package.json b/dobot-serial/sub/ui/package.json new file mode 100644 index 0000000..67cc05b --- /dev/null +++ b/dobot-serial/sub/ui/package.json @@ -0,0 +1,35 @@ +{ + "name": "@repo/ui", + "version": "1.0.0", + "private": true, + "main": "./src/index.ts", + "types": "./src/index.ts", + "scripts": { + "lint": "eslint . --max-warnings 20", + "type-check": "tsc --pretty --noEmit" + }, + "devDependencies": { + "@ktaicoder/hw-pet": "^1.2.9", + "@mui/icons-material": "^5.15.17", + "@mui/material": "^5.15.17", + "@repo/eslint-config": "workspace:*", + "@repo/typescript-config": "workspace:*", + "@types/eslint": "^8.44.7", + "@types/node": "^18.19.0", + "@types/react": "^18.3.2", + "@types/react-dom": "^18.3.0", + "clsx": "^2.1.0", + "eslint": "^8.57.0", + "next": "^14.2.3", + "react": "^18.3.1", + "typescript": "^5.3.3" + }, + "peerDependencies": { + "@ktaicoder/hw-pet": "^1.2.9", + "@mui/icons-material": "^5", + "@mui/material": "^5", + "clsx": "^2", + "next": "^14", + "react": "^18" + } +} \ No newline at end of file diff --git a/dobot-serial/sub/ui/src/components/ConnectButton.tsx b/dobot-serial/sub/ui/src/components/ConnectButton.tsx new file mode 100644 index 0000000..0e0db38 --- /dev/null +++ b/dobot-serial/sub/ui/src/components/ConnectButton.tsx @@ -0,0 +1,105 @@ +import type { ConnectionState } from '@ktaicoder/hw-pet' +import type { SxProps } from '@mui/material' +import { Box, ButtonBase } from '@mui/material' +import { clsx } from 'clsx' +import { flatSx } from '../util' + +interface Props { + sx?: SxProps + className?: string + style?: React.CSSProperties + connectionState: ConnectionState + onClickDisconnectBtn: React.MouseEventHandler + onClickConnectBtn: React.MouseEventHandler +} + +export function ConnectButton(props: Props) { + const { sx, className, style, connectionState, onClickConnectBtn, onClickDisconnectBtn } = props + + return ( + <> + {connectionState === 'connected' && ( + + Connected + + )} + + {connectionState === 'disconnected' && ( + + Disconnected + + )} + + {connectionState === 'connecting' && ( + + Connecting... + + )} + + ) +} + +const rootSx: SxProps = { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: 40, + mx: 'auto', + mt: 1, + bgcolor: 'primary.main', + color: '#fff', + boxShadow: 3, + maxWidth: 200, + borderRadius: 1, + fontWeight: 400, + fontSize: '1.1rem', + '&.x_connected': { + bgcolor: 'primary.main', + borderRadius: '20px / 50%', + fontWeight: 500, + fontSize: '1.15rem', + position: 'relative', + '&::before': { + position: 'absolute', + top: '50%', + right: 12, + transform: 'translateY(-50%)', + content: '"×"', + fontSize: '0.9rem', + }, + }, + '&.x_disconnected': { + bgcolor: 'secondary.main', + position: 'relative', + '&::before': { + position: 'absolute', + top: '50%', + right: 12, + transform: 'translateY(-50%)', + content: '"☝"', + fontSize: '0.9rem', + }, + }, + '&.x_connecting': { + bgcolor: '#e91e63', + borderRadius: 1, + boxShadow: 'none', + maxWidth: '90%', + }, +} diff --git a/dobot-serial/sub/ui/src/components/HardwareImageBox.tsx b/dobot-serial/sub/ui/src/components/HardwareImageBox.tsx new file mode 100644 index 0000000..2bb93de --- /dev/null +++ b/dobot-serial/sub/ui/src/components/HardwareImageBox.tsx @@ -0,0 +1,37 @@ +import type { SxProps } from '@mui/material' +import { Box } from '@mui/material' +import clsx from 'clsx' +import { flatSx } from '../util' + +interface Props { + sx?: SxProps + className?: string + style?: React.CSSProperties + src: string +} + +export function HardwareImageBox(props: Props) { + const { sx, className, style, src } = props + return ( + + + + ) +} diff --git a/dobot-serial/sub/ui/src/components/HardwareNameBox.tsx b/dobot-serial/sub/ui/src/components/HardwareNameBox.tsx new file mode 100644 index 0000000..fd814d9 --- /dev/null +++ b/dobot-serial/sub/ui/src/components/HardwareNameBox.tsx @@ -0,0 +1,38 @@ +import type { SxProps } from '@mui/material' +import { Typography } from '@mui/material' +import { flatSx } from '../util' +import clsx from 'clsx' + +interface Props { + sx?: SxProps + className?: string + style?: React.CSSProperties + title: string +} + +export function HardwareNameBox(props: Props) { + const { sx, className, style, title } = props + return ( + + {title} + + ) +} diff --git a/dobot-serial/sub/ui/src/components/MediaIconBox.tsx b/dobot-serial/sub/ui/src/components/MediaIconBox.tsx new file mode 100644 index 0000000..bde3f98 --- /dev/null +++ b/dobot-serial/sub/ui/src/components/MediaIconBox.tsx @@ -0,0 +1,31 @@ +import type { SxProps } from '@mui/material' +import { Stack } from '@mui/material' +import clsx from 'clsx' +import React from 'react' +import { flatSx } from '../util' + +interface Props { + sx?: SxProps + className?: string + style?: React.CSSProperties + children?: React.ReactNode + mediaIcon: string +} + +export function MediaIconBox(props: Props) { + const { sx, className, style, mediaIcon, children } = props + return ( + + + {children} + + ) +} diff --git a/dobot-serial/sub/ui/src/components/index.ts b/dobot-serial/sub/ui/src/components/index.ts new file mode 100644 index 0000000..baeeb07 --- /dev/null +++ b/dobot-serial/sub/ui/src/components/index.ts @@ -0,0 +1,4 @@ +export * from './ConnectButton' +export * from './HardwareImageBox' +export * from './HardwareNameBox' +export * from './MediaIconBox' diff --git a/dobot-serial/sub/ui/src/hooks/index.ts b/dobot-serial/sub/ui/src/hooks/index.ts new file mode 100644 index 0000000..c816de3 --- /dev/null +++ b/dobot-serial/sub/ui/src/hooks/index.ts @@ -0,0 +1 @@ +export * from './usePet' diff --git a/dobot-serial/sub/ui/src/hooks/usePet.ts b/dobot-serial/sub/ui/src/hooks/usePet.ts new file mode 100644 index 0000000..2ca65db --- /dev/null +++ b/dobot-serial/sub/ui/src/hooks/usePet.ts @@ -0,0 +1,66 @@ +'use client' + +import type { + ConnectionState, + HPetCommandRunnerClassType, + IHPetCommandRunner, +} from '@ktaicoder/hw-pet' +import { HPet, HPetNotifyEventKeys } from '@ktaicoder/hw-pet' +import type { ReadonlyURLSearchParams } from 'next/navigation' +import { useEffect, useMemo, useState } from 'react' + +interface Result { + pet: HPet | undefined + commandRunner: T | undefined + connectionState: ConnectionState +} + +export function usePet>( + hwId: string, + commandRunnerClass: C, + searchParams: ReadonlyURLSearchParams, +): Result> { + const iframeToken = useMemo(() => getIframeToken(searchParams.get('iframeToken')), [searchParams]) + const [connectionState, setConnectionState] = useState('disconnected') + const [commandRunner, setCommandRunner] = useState>() + const [petInstance, setPetInstance] = useState() + + useEffect(() => { + const pet = new HPet({ + iframeToken, + hwId, + commandRunnerClass, + }) + pet.notifyEvents.on(HPetNotifyEventKeys.CommandRunner.stateChanged, (data) => { + const { state, commandRunner } = data + if (state === 'started') { + setCommandRunner(commandRunner as InstanceType) + } else { + setCommandRunner(undefined) + } + }) + pet.notifyEvents.on(HPetNotifyEventKeys.connectionStateChanged, setConnectionState) + + pet.start() + setPetInstance(pet) + return () => { + // all event listeners will be automatically removed + pet.stop() + setCommandRunner(undefined) + } + }, [hwId, iframeToken, commandRunnerClass]) + + return useMemo( + () => ({ pet: petInstance, commandRunner, connectionState }), + [petInstance, commandRunner, connectionState], + ) +} + +export function getIframeToken(iframeToken: string | null): string { + if (iframeToken) { + return iframeToken + } + + console.log('invalid iframeToken:', iframeToken) + return 'unknown' +} diff --git a/dobot-serial/sub/ui/src/index.ts b/dobot-serial/sub/ui/src/index.ts new file mode 100644 index 0000000..7f7e7ed --- /dev/null +++ b/dobot-serial/sub/ui/src/index.ts @@ -0,0 +1,3 @@ +export * from './components' +export * from './hooks' +export * from './util' diff --git a/dobot-serial/sub/ui/src/util/event-utils.ts b/dobot-serial/sub/ui/src/util/event-utils.ts new file mode 100644 index 0000000..4be5f3f --- /dev/null +++ b/dobot-serial/sub/ui/src/util/event-utils.ts @@ -0,0 +1,33 @@ +export const isTabKeyEvent = (e: React.KeyboardEvent): boolean => { + return !e.shiftKey && e.key === 'Tab' +} + +export const isEnterOrTabKeyEvent = (e: React.KeyboardEvent): boolean => { + return e.key === 'Enter' || (!e.shiftKey && e.key === 'Tab') +} + +export const isEnterKeyEvent = (e: React.KeyboardEvent): boolean => { + return e.key === 'Enter' +} + +export const isEscapeKeyEvent = (e: React.KeyboardEvent): boolean => { + return e.key === 'Escape' +} + +export const isTouchEvent = (event: MouseEvent | TouchEvent): event is TouchEvent => { + // eslint-disable-next-line @typescript-eslint/prefer-optional-chain + return Boolean((event as TouchEvent).touches && (event as TouchEvent).touches.length) +} + +export const isMouseEvent = (event: MouseEvent | TouchEvent): event is MouseEvent => { + return Boolean( + ((event as MouseEvent).clientX || (event as MouseEvent).clientX === 0) && + ((event as MouseEvent).clientY || (event as MouseEvent).clientY === 0), + ) +} + +export const blurEventTarget = (event: any) => { + if (typeof event.target?.blur === 'function') { + event.target.blur() + } +} diff --git a/dobot-serial/sub/ui/src/util/index.ts b/dobot-serial/sub/ui/src/util/index.ts new file mode 100644 index 0000000..a707be4 --- /dev/null +++ b/dobot-serial/sub/ui/src/util/index.ts @@ -0,0 +1,4 @@ +export * from './event-utils' +export * from './misc-utils' +export * from './sx-props' +export * from './type-check' diff --git a/dobot-serial/sub/ui/src/util/misc-utils.ts b/dobot-serial/sub/ui/src/util/misc-utils.ts new file mode 100644 index 0000000..85d0f7e --- /dev/null +++ b/dobot-serial/sub/ui/src/util/misc-utils.ts @@ -0,0 +1,90 @@ +export function sleepAsync(milli: number): Promise { + return new Promise((resolve) => { + setTimeout(resolve, milli) + }) +} + +export function isValidURL(str: string | null | undefined): boolean { + if (typeof str !== 'string') return false + if (str.length === 0) return false + try { + return Boolean(new URL(str)) + } catch (e) { + return false + } +} + +const queryElement = (el: HTMLElement | Document | null | undefined, selector: string) => { + if (!el) return null + return el.querySelector(selector) +} + +export const requestFocusSelector = ( + parent: HTMLElement | Document | undefined | null, + selector: string, + delay = -1, +) => { + if (!parent) return + if (delay < 0) { + const elem = parent.querySelector(selector) + elem?.focus() + return + } + + setTimeout(() => { + const elem = parent.querySelector(selector) + elem?.focus() + }, delay) +} + +export const requestSelector = ( + el: HTMLElement | Document | null | undefined, + selector: string, + callback: (elemnt: HTMLElement) => unknown, + timeout = -1, +) => { + if (timeout < 0) { + const element = queryElement(el, selector) + if (element) { + callback(element as HTMLElement) + } + return + } + + setTimeout(() => { + const element = queryElement(el, selector) + if (element) { + callback(element as HTMLElement) + } + }, timeout) +} + +export function isWebSerialSupportBrowser(): boolean { + return window.navigator && 'serial' in window.navigator +} + +export function isTouchDevice(): boolean { + return ( + typeof window !== 'undefined' && + typeof navigator !== 'undefined' && + ('ontouchstart' in window || navigator.maxTouchPoints > 0) + ) +} + +export function matchesOrClosest( + target: Element, + selector: string, +): T | undefined { + const found = target.matches(selector) ? target : target.closest(selector) + if (found) { + return found as T + } + return undefined +} + +export function cancelCtx(ctx?: { canceled: boolean; cancel?: () => void }) { + if (!ctx) return + if (ctx.canceled) return + ctx.canceled = true + ctx.cancel?.() +} diff --git a/dobot-serial/sub/ui/src/util/sx-props.ts b/dobot-serial/sub/ui/src/util/sx-props.ts new file mode 100644 index 0000000..f2a32c8 --- /dev/null +++ b/dobot-serial/sub/ui/src/util/sx-props.ts @@ -0,0 +1,15 @@ +import type { SxProps, Theme } from '@mui/material' + +/** + * Creates an array by flattening SxProps + * @param sxArray - array of SxProps + * @returns SxProps + */ +export function flatSx( + ...sxArray: (SxProps | undefined | false | null)[] +): SxProps { + return sxArray + .filter(Boolean) // filter undefined + .flatMap((sx) => (Array.isArray(sx) ? sx : [sx ?? false])) + .filter((it) => it !== false) +} diff --git a/dobot-serial/sub/ui/src/util/type-check.ts b/dobot-serial/sub/ui/src/util/type-check.ts new file mode 100644 index 0000000..9eb05db --- /dev/null +++ b/dobot-serial/sub/ui/src/util/type-check.ts @@ -0,0 +1,9 @@ +export const isObject = (value: unknown): value is Record => + value !== null && typeof value === 'object' +export const isFunction = (value: unknown): value is (...args: any) => any => + typeof value === 'function' + +export const isString = (value: unknown): value is string => typeof value === 'string' +export const isBoolean = (value: unknown): value is boolean => typeof value === 'boolean' +export const isNumber = (value: unknown): value is number => typeof value === 'number' +export const isUndef = (value: unknown): value is undefined => typeof value === 'undefined' diff --git a/dobot-serial/sub/ui/tsconfig.json b/dobot-serial/sub/ui/tsconfig.json new file mode 100644 index 0000000..49ad490 --- /dev/null +++ b/dobot-serial/sub/ui/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@repo/typescript-config/react-library.json", + "compilerOptions": { + "outDir": "dist", + }, + "include": ["src", ".eslintrc.cjs"], + "exclude": ["node_modules", "dist"], +} diff --git a/dobot-serial/tsconfig.json b/dobot-serial/tsconfig.json new file mode 100644 index 0000000..c8a018d --- /dev/null +++ b/dobot-serial/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@repo/typescript-config/base.json" +} diff --git a/dobot-serial/turbo.json b/dobot-serial/turbo.json new file mode 100644 index 0000000..1d34d7c --- /dev/null +++ b/dobot-serial/turbo.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://turbo.build/schema.json", + "globalDependencies": ["**/.env.*local", "**/.env.production", "**/.env"], + "globalEnv": [ + "NEXT_PUBLIC_BASE_PATH", + "NEXT_PUBLIC_PRODUCTION", + "NEXT_PUBLIC_DEBUG" + ], + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": [".next/**", "!.next/cache/**"] + }, + "lint": {}, + "dev": { + "cache": false, + "persistent": true + } + } +}