diff --git a/apps/api/src/pkg/keys/service.ts b/apps/api/src/pkg/keys/service.ts index edecd73ffc..2065a95e63 100644 --- a/apps/api/src/pkg/keys/service.ts +++ b/apps/api/src/pkg/keys/service.ts @@ -470,7 +470,13 @@ export class KeyService { duration: data.key.ratelimitDuration, }; } + for (const r of req.ratelimits ?? []) { + if (r.name === "default" && "default" in ratelimits) { + // it's already added above + continue; + } + if (typeof r.limit !== "undefined" && typeof r.duration !== "undefined") { ratelimits[r.name] = { identity: data.identity?.id ?? data.key.id, diff --git a/apps/api/src/routes/v1_keys_verifyKey.test.ts b/apps/api/src/routes/v1_keys_verifyKey.test.ts index dd89176c55..d97e9d1952 100644 --- a/apps/api/src/routes/v1_keys_verifyKey.test.ts +++ b/apps/api/src/routes/v1_keys_verifyKey.test.ts @@ -384,6 +384,44 @@ describe("with ratelimit override", () => { }); }); +describe("with default ratelimit", () => { + test("uses the on-key defined settings", { timeout: 20000 }, async (t) => { + const h = await IntegrationHarness.init(t); + const key = new KeyV1({ prefix: "test", byteLength: 16 }).toString(); + await h.db.primary.insert(schema.keys).values({ + id: newId("test"), + keyAuthId: h.resources.userKeyAuth.id, + hash: await sha256(key), + start: key.slice(0, 8), + workspaceId: h.resources.userWorkspace.id, + createdAt: new Date(), + ratelimitLimit: 10, + ratelimitDuration: 60_000, + ratelimitAsync: false, + }); + + const res = await h.post({ + url: "/v1/keys.verifyKey", + headers: { + "Content-Type": "application/json", + }, + body: { + key, + apiId: h.resources.userApi.id, + ratelimits: [ + { + name: "default", + }, + ], + }, + }); + expect(res.status, `expected 200, received: ${JSON.stringify(res, null, 2)}`).toBe(200); + expect(res.body.valid).toBe(true); + expect(res.body.ratelimit).toBeDefined(); + expect(res.body.ratelimit!.limit).toEqual(10); + }); +}); + describe("with ratelimit", () => { describe("with valid key", () => { test.skip( diff --git a/apps/dashboard/components/dashboard/command-menu.tsx b/apps/dashboard/components/dashboard/command-menu.tsx index e262ef810c..7beacaace7 100644 --- a/apps/dashboard/components/dashboard/command-menu.tsx +++ b/apps/dashboard/components/dashboard/command-menu.tsx @@ -68,19 +68,16 @@ export function CommandMenu() { const DiscordCommand: React.FC = () => { const router = useRouter(); return ( - router.push("/discord")}> + router.push("https://unkey.com/discord")}> - + Go to Discord diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index e563cb57a8..cad9be83f7 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -22,7 +22,7 @@ "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-dialog": "^1.0.5", - "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-progress": "^1.0.3", diff --git a/apps/www/content/blog/learn-by-building.mdx b/apps/www/content/blog/learn-by-building.mdx new file mode 100644 index 0000000000..f1b4426274 --- /dev/null +++ b/apps/www/content/blog/learn-by-building.mdx @@ -0,0 +1,171 @@ +--- +date: 2024-09-12 +title: Learn by building +image: "/images/blog-images/covers/learn-by-building.png" +description: "What I learned developing a full application for the first time." +author: michael +tags: ["marketing"] +--- + + + + +Last May I bought a [Bambu Labs A1](https://bambulab.com/en-us/a1). Mainly as a hobby and to make some parts for some home projects. While browsing for interesting creations from the community on [Makerworld](https://makerworld.com/en), I had the idea of creating myself a web app to store personal projects to reference and save notes and images of the progress. + +## How I built my project + +I am a relatively new developer, so planning larger projects like this is a new experience. + +To build this project I needed: + +- Authentication +- Database +- Web application +- Route protection + +I went with: + +- Auth.js +- sqlite db and Drizzle ORM +- NextJS +- Unkey ratelimit protection + + I started with a basic database schema planning. I found that for me its always a good place to start. It allows me to get an idea of the data and how interaction with that data will happen. + +### Setup + +Next I gave myself a good starting point to quickly setup and hit the ground running. I found that the faster I can get something working the better for my ADHD. So I used the [T3 stack](https://create.t3.gg/) to give me a good head start. + +```shell +pnpm create t3-app@latest +``` + +Options used: +Using the playground + + +### Build +Continuing that trend I added some basic [shadcn](https://ui.shadcn.com/) components to get started on the UI. +In just a short period of time I had a half decent looking app. But that was the easy part. + +So UI being functional enough, I started digging into the api/server side of things. I set up the `Drizzle` schema and `tRPC` routes. Sure I may have needed the `tRPC` and `Drizzle` docs open the entire time. But hey, that is what they are for. +My first real hurdle was about now. As usual, I was starting to over think the schema and layout and whatever else. keeping on track with a larger project is a challenge for me. + +When planning out the db schema I started adding more columns than needed. I also added references I would not need making it more complicated than it needed to be. I often have to stop myself from bouncing to another file if an idea pops into my head. +This was a good experience as it allowed me to think about self restraint and management. Just telling myself that things are fluid and can be changed later was very helpful. Nothing is perfect on the first draft so building things in a way that allows for changes later is important. For me being flexible is the way forward and not over thinking and getting stuck on a single task. + +### Typescript + +I have been working in a Typescript project for about a year now, but because a lot of the code was implemented when I got to Unkey. I often struggled with debugging errors. +On this project because I implemented code from start to finish, I got a lot more familiar with debugging typescript errors. + +To make my life a bit easier, I used [zod](https://zod.dev/) to manage the tRPC routes. + +```typescript + getProjectsByCategory: publicProcedure + .input( + z.object({ + category: z.string().min(3), + }), + ) + .query(async ({ ctx, input }) => { + const project = await ctx.db.query.projects.findMany({ + where: eq(projects.category, input.category.toUpperCase()), + orderBy: (projects, { desc }) => [desc(projects.createdAt)], + limit: 50, + with: { steps: true }, + }); + return project; + }), +``` + +And on the form side a controlled form element with `zod` and `react-hook-form` + +```typescript +const formSchema = z.object({ + projectName: z.string().min(2).max(50), + category: z.string().min(2).max(50), + projectDescription: z + .string() + .min(10, { message: "Must be 10 or more characters long" }) + .max(500, { message: "Must be less than 500 characters long" }), + projectImage: z + .instanceof(File) + .refine( + (file) => !ACCEPTED_IMAGE_TYPES.includes(file?.type), + "Only .jpg, .jpeg and .png formats are supported.", + ) + .optional(), +}); +``` +Keeping my types in check made it easy to track down errors from human error. things like passing the wrong type to routes or incorrect variable names. Just makes less thing I need to worry about once setup so I can focus on the things that need to be done and not tracking down a typo or something. + + +### Ratelimit +If I ever want to launch this live I figured it would be a good idea to limit abuse on any of the secured routes. The choice was pretty easy being as I work for a company that has a `Ratelimit` sdk. + +```shell +pnpm add @unkey/ratelimit + +``` + +Unkey makes this incredible easy it take a couple of steps to implement. I used the docs as a reference point. [docs](https://www.unkey.com/docs/libraries/ts/ratelimit) + +### Created ratelimit procedure + +```typescript +export const rateLimitedProcedure = ({ + limit, + duration, +}: { + limit: number; + duration: number; +}) => + protectedProcedure.use(async (opts) => { + const unkey = new Ratelimit({ + rootKey: env.UNKEY_ROOT_KEY, + namespace: `trpc_${opts.path}`, + limit: limit ?? 3, + duration: duration ? `${duration}s` : `${5}s`, + }); + + const ratelimit = await unkey.limit(opts.ctx.session.user.id); + + if (!ratelimit.success) { + throw new TRPCError({ + code: "TOO_MANY_REQUESTS", + message: JSON.stringify(ratelimit), + }); + } + + return opts.next({ + ctx: { + ...opts.ctx, + remaining: ratelimit.remaining, + }, + }); + }); +``` + +And then used like this on any route you want to `ratelimit` + +```typescript + create: rateLimitedProcedure({ limit: 3, duration: 5 }) + .input( + z.object({ + projectName: z.string().min(3), + projectDescription: z.string(), + category: z.string(), + projectImage: z.string().optional(), + }), + ) +``` + +This is probably what took the longest. My experience is limited with `tRPC` routes and `ratelimiting`. I was stuck on this for a little while, as I have never really worked with tRPC and ratelimiting on my own. I tried to work through this, but needed to reach out to get help. Just like everyone else I hate bothering people but sometimes the best path forward to reaching out to someone else. + +## Conclusion + +In making this project I learned a hell of a lot. I now have a more solid understanding of client/server communications. How to debug and fix `Typescript` errors more effectively. When to ask for help from someone who has more experience, while docs will get you pretty far there is no substitute for another person to pair with. Big thanks to [James](https://x.com/james_r_perkins) and [Andreas](https://x.com/chronark_) for all the help over the last year. I would like to add more features to this in the future, but for now I have added the example into Unkey's templates page for anyone interested in checking out the code. + +**Example** +[Unkey ratelimiting with TRPC + Drizzle](https://www.unkey.com/templates/unkey-trpc-ratelimit) diff --git a/apps/www/public/images/blog-images/covers/learn-by-building.png b/apps/www/public/images/blog-images/covers/learn-by-building.png new file mode 100644 index 0000000000..53d6b16aac Binary files /dev/null and b/apps/www/public/images/blog-images/covers/learn-by-building.png differ diff --git a/apps/www/public/images/blog-images/learn-by-building/createt3.png b/apps/www/public/images/blog-images/learn-by-building/createt3.png new file mode 100644 index 0000000000..631e1e905f Binary files /dev/null and b/apps/www/public/images/blog-images/learn-by-building/createt3.png differ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3d2e176fd8..ab3167927b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -262,8 +262,8 @@ importers: specifier: ^1.0.5 version: 1.0.5(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-dropdown-menu': - specifier: ^2.0.6 - version: 2.0.6(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + specifier: ^2.1.1 + version: 2.1.1(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-label': specifier: ^2.0.2 version: 2.0.2(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) @@ -1223,7 +1223,7 @@ importers: devDependencies: checkly: specifier: latest - version: 4.8.1(@types/node@20.14.9)(typescript@5.5.3) + version: 4.9.0(@types/node@20.14.9)(typescript@5.5.3) ts-node: specifier: 10.9.1 version: 10.9.1(@types/node@20.14.9)(typescript@5.5.3) @@ -7252,6 +7252,26 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: false + /@radix-ui/react-arrow@1.1.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@types/react': 18.2.79 + '@types/react-dom': 18.2.25 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + dev: false + /@radix-ui/react-arrow@1.1.0(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==} peerDependencies: @@ -7767,14 +7787,14 @@ packages: '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-context': 1.1.0(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-dismissable-layer': 1.1.0(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.0(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.2.79)(react@18.3.1) '@radix-ui/react-focus-scope': 1.1.0(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.2)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(react@18.3.1) '@radix-ui/react-portal': 1.1.1(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-primitive': 2.0.0(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.2)(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -7925,6 +7945,30 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: false + /@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@types/react': 18.2.79 + '@types/react-dom': 18.2.25 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + dev: false + /@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==} peerDependencies: @@ -7966,32 +8010,31 @@ packages: '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-primitive': 2.0.0(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.2)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.0(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) dev: true - /@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==} + /@radix-ui/react-dropdown-menu@2.1.1(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-menu': 2.0.6(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-menu': 2.1.1(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.2.79)(react@18.3.1) '@types/react': 18.2.79 '@types/react-dom': 18.2.25 react: 18.3.1 @@ -8034,7 +8077,7 @@ packages: react: 18.3.1 dev: false - /@radix-ui/react-focus-guards@1.1.0(react@18.3.1): + /@radix-ui/react-focus-guards@1.1.0(@types/react@18.2.79)(react@18.3.1): resolution: {integrity: sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==} peerDependencies: '@types/react': '*' @@ -8043,8 +8086,8 @@ packages: '@types/react': optional: true dependencies: + '@types/react': 18.2.79 react: 18.3.1 - dev: true /@radix-ui/react-focus-scope@1.0.0(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-C4SWtsULLGf/2L4oGeIHlvWQx7Rf+7cX/vKOAD2dXW0A1b5QXwi3wWeaEgW+wn+SEVrraMUk05vLU9fZZz5HbQ==} @@ -8105,6 +8148,28 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: false + /@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@types/react': 18.2.79 + '@types/react-dom': 18.2.25 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + dev: false + /@radix-ui/react-focus-scope@1.1.0(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==} peerDependencies: @@ -8198,6 +8263,20 @@ packages: '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.2)(react@18.3.1) '@types/react': 18.3.2 react: 18.3.1 + dev: false + + /@radix-ui/react-id@1.1.0(react@18.3.1): + resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.2)(react@18.3.1) + react: 18.3.1 + dev: true /@radix-ui/react-label@2.0.2(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==} @@ -8241,42 +8320,41 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: false - /@radix-ui/react-menu@2.0.6(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==} + /@radix-ui/react-menu@2.1.1(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-oa3mXRRVjHi6DZu/ghuzdylyjaMXLymx83irM7hTxutQbD+7IhPKdMdRHD26Rm+kHRrWcrUkkRPv5pd47a2xFQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true '@types/react-dom': optional: true dependencies: - '@babel/runtime': 7.25.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-direction': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.79)(react@18.3.1) '@types/react': 18.2.79 '@types/react-dom': 18.2.25 aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.5(@types/react@18.2.79)(react@18.3.1) + react-remove-scroll: 2.5.7(@types/react@18.2.79)(react@18.3.1) dev: false /@radix-ui/react-popover@1.0.7(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): @@ -8439,6 +8517,35 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: false + /@radix-ui/react-popper@1.2.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@floating-ui/react-dom': 2.1.1(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-arrow': 1.1.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@radix-ui/rect': 1.1.0 + '@types/react': 18.2.79 + '@types/react-dom': 18.2.25 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + dev: false + /@radix-ui/react-popper@1.2.0(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==} peerDependencies: @@ -8459,7 +8566,7 @@ packages: '@radix-ui/react-primitive': 2.0.0(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-use-rect': 1.1.0(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.0(@types/react@18.2.79)(react@18.3.1) '@radix-ui/react-use-size': 1.1.0(react@18.3.1) '@radix-ui/rect': 1.1.0 react: 18.3.1 @@ -8540,6 +8647,27 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: false + /@radix-ui/react-portal@1.1.1(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@types/react': 18.2.79 + '@types/react-dom': 18.2.25 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + dev: false + /@radix-ui/react-portal@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==} peerDependencies: @@ -8676,6 +8804,26 @@ packages: '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + dev: false + + /@radix-ui/react-presence@1.1.0(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.2)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.2)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + dev: true /@radix-ui/react-primitive@1.0.0(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-EyXe6mnRlHZ8b6f4ilTDrXmkLShICIuOTTj0GX4w1rp+wSxf3+TD05u1UOITC8VsJ2a9nwHvdXtOXEOl0Cw/zQ==} @@ -8804,7 +8952,7 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.2)(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) dev: true @@ -8831,35 +8979,6 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: false - /@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@babel/runtime': 7.25.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-direction': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.79)(react@18.3.1) - '@types/react': 18.2.79 - '@types/react-dom': 18.2.25 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - /@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} peerDependencies: @@ -9147,6 +9266,20 @@ packages: '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.2)(react@18.3.1) '@types/react': 18.3.2 react: 18.3.1 + dev: false + + /@radix-ui/react-slot@1.1.0(react@18.3.1): + resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.2)(react@18.3.1) + react: 18.3.1 + dev: true /@radix-ui/react-switch@1.0.3(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==} @@ -9391,13 +9524,13 @@ packages: '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-context': 1.1.0(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-dismissable-layer': 1.1.0(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.2)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(react@18.3.1) '@radix-ui/react-popper': 1.2.0(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-portal': 1.1.1(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(react-dom@18.3.1)(react@18.3.1) '@radix-ui/react-primitive': 2.0.0(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.2)(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(react@18.3.1) '@radix-ui/react-visually-hidden': 1.1.0(react-dom@18.3.1)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -9529,6 +9662,20 @@ packages: '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.2)(react@18.3.1) '@types/react': 18.3.2 react: 18.3.1 + dev: false + + /@radix-ui/react-use-controllable-state@1.1.0(react@18.3.1): + resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.2)(react@18.3.1) + react: 18.3.1 + dev: true /@radix-ui/react-use-escape-keydown@1.0.0(react@18.3.1): resolution: {integrity: sha512-JwfBCUIfhXRxKExgIqGa4CQsiMemo1Xt0W/B4ei3fpzpvPENKpMKQ8mZSB6Acj3ebrAEgi2xiQvcI1PAAodvyg==} @@ -9569,6 +9716,20 @@ packages: react: 18.3.1 dev: false + /@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.2.79)(react@18.3.1): + resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@types/react': 18.2.79 + react: 18.3.1 + dev: false + /@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.2)(react@18.3.1): resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==} peerDependencies: @@ -9581,6 +9742,20 @@ packages: '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.2)(react@18.3.1) '@types/react': 18.3.2 react: 18.3.1 + dev: false + + /@radix-ui/react-use-escape-keydown@1.1.0(react@18.3.1): + resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.2)(react@18.3.1) + react: 18.3.1 + dev: true /@radix-ui/react-use-layout-effect@1.0.0(react@18.3.1): resolution: {integrity: sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ==} @@ -9687,7 +9862,7 @@ packages: react: 18.3.1 dev: false - /@radix-ui/react-use-rect@1.1.0(react@18.3.1): + /@radix-ui/react-use-rect@1.1.0(@types/react@18.2.79)(react@18.3.1): resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==} peerDependencies: '@types/react': '*' @@ -9697,8 +9872,8 @@ packages: optional: true dependencies: '@radix-ui/rect': 1.1.0 + '@types/react': 18.2.79 react: 18.3.1 - dev: true /@radix-ui/react-use-size@1.0.1(@types/react@18.2.79)(react@18.3.1): resolution: {integrity: sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==} @@ -9730,6 +9905,20 @@ packages: react: 18.3.1 dev: false + /@radix-ui/react-use-size@1.1.0(@types/react@18.2.79)(react@18.3.1): + resolution: {integrity: sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.79)(react@18.3.1) + '@types/react': 18.2.79 + react: 18.3.1 + dev: false + /@radix-ui/react-use-size@1.1.0(react@18.3.1): resolution: {integrity: sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==} peerDependencies: @@ -9831,7 +10020,6 @@ packages: /@radix-ui/rect@1.1.0: resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==} - dev: true /@react-email/body@0.0.7(react@18.3.1): resolution: {integrity: sha512-vjJ5P1MUNWV0KNivaEWA6MGj/I3c764qQJMsKjCHlW6mkFJ4SXbm2OlQFtKAb++Bj8LDqBlnE6oW77bWcMc0NA==} @@ -12964,8 +13152,8 @@ packages: get-func-name: 2.0.2 dev: true - /checkly@4.8.1(@types/node@20.14.9)(typescript@5.5.3): - resolution: {integrity: sha512-LyVxHVOqjZ6k/QXGZQhZgnG7stL5mYfzu+Vl5hkdh2ZKDm/MLk4Q+gRKAyMLOjMN66jrJN1ZM1K3zlLt2/EJcg==} + /checkly@4.9.0(@types/node@20.14.9)(typescript@5.5.3): + resolution: {integrity: sha512-LqohEntErF7dJaJPsEpjvr/O9wUfzBRac6DOXgFDMEw+dNi19oBAcspdOqVGjPjMoCZ9/s5b5tSJI1pusY4mJQ==} engines: {node: '>=16.0.0'} hasBin: true dependencies: @@ -21290,6 +21478,22 @@ packages: react: 18.3.1 react-style-singleton: 2.2.1(@types/react@18.3.5)(react@18.3.1) tslib: 2.7.0 + dev: false + + /react-remove-scroll-bar@2.3.6(react@18.3.1): + resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + react: 18.3.1 + react-style-singleton: 2.2.1(@types/react@18.3.5)(react@18.3.1) + tslib: 2.7.0 + dev: true /react-remove-scroll@2.5.10(@types/react@18.2.79)(react@18.3.1): resolution: {integrity: sha512-m3zvBRANPBw3qxVVjEIPEQinkcwlFZ4qyomuWVpNJdv4c6MvHfXV0C3L9Jx5rr3HeBHKNRX+1jreB5QloDIJjA==} @@ -21340,7 +21544,7 @@ packages: optional: true dependencies: react: 18.3.1 - react-remove-scroll-bar: 2.3.6(@types/react@18.3.5)(react@18.3.1) + react-remove-scroll-bar: 2.3.6(react@18.3.1) react-style-singleton: 2.2.1(@types/react@18.3.5)(react@18.3.1) tslib: 2.7.0 use-callback-ref: 1.3.2(@types/react@18.3.5)(react@18.3.1) @@ -21385,6 +21589,25 @@ packages: use-sidecar: 1.1.2(@types/react@18.3.5)(react@18.3.1) dev: false + /react-remove-scroll@2.5.7(@types/react@18.2.79)(react@18.3.1): + resolution: {integrity: sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.79 + react: 18.3.1 + react-remove-scroll-bar: 2.3.6(@types/react@18.2.79)(react@18.3.1) + react-style-singleton: 2.2.1(@types/react@18.2.79)(react@18.3.1) + tslib: 2.7.0 + use-callback-ref: 1.3.2(@types/react@18.2.79)(react@18.3.1) + use-sidecar: 1.1.2(@types/react@18.2.79)(react@18.3.1) + dev: false + /react-remove-scroll@2.5.7(react@18.3.1): resolution: {integrity: sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==} engines: {node: '>=10'} @@ -21396,7 +21619,7 @@ packages: optional: true dependencies: react: 18.3.1 - react-remove-scroll-bar: 2.3.6(@types/react@18.3.5)(react@18.3.1) + react-remove-scroll-bar: 2.3.6(react@18.3.1) react-style-singleton: 2.2.1(@types/react@18.3.5)(react@18.3.1) tslib: 2.7.0 use-callback-ref: 1.3.2(@types/react@18.3.5)(react@18.3.1)