diff --git a/flags-sdk/flagsmith/.eslintrc.json b/flags-sdk/flagsmith/.eslintrc.json new file mode 100755 index 000000000..175482683 --- /dev/null +++ b/flags-sdk/flagsmith/.eslintrc.json @@ -0,0 +1,11 @@ +{ + "root": true, + "extends": "next/core-web-vitals", + "rules": { + "@typescript-eslint/require-await": "off", + "@typescript-eslint/no-misused-promises": "off", + "import/order": "off", + "camelcase": "off", + "no-console": "off" + } +} diff --git a/flags-sdk/flagsmith/.gitignore b/flags-sdk/flagsmith/.gitignore new file mode 100644 index 000000000..fd3dbb571 --- /dev/null +++ b/flags-sdk/flagsmith/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# 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 + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/flags-sdk/flagsmith/README.md b/flags-sdk/flagsmith/README.md new file mode 100644 index 000000000..47b44a523 --- /dev/null +++ b/flags-sdk/flagsmith/README.md @@ -0,0 +1,66 @@ +# flagsmith Flags SDK Example + +This example uses [flagsmith](https://flagsmith.com/) for feature flags with the [Flags SDK](https://flags-sdk.dev) and the [Flags SDK flagsmith adapter](https://flags-sdk.dev/docs/api-reference/adapters/flagsmith) along with the [Flags Explorer](https://vercel.com/docs/workflow-collaboration/feature-flags/using-vercel-toolbar). + +## Demo + +[https://flags-sdk-flagsmith.vercel.app/](https://flags-sdk-flagsmith.vercel.app/) + +## How it works + +This demo uses two feature flags defined in code control the visibility of two banners on the page. +Both flags are configured to show/hide each banner 50% of the time. + +Once you visit the page, you can see a variation of both/one/none of the banners. +Since this example is using a stable id to identify users, you will see the same variation until you reset your id. + +To test different variations, you can use the Dev Tools at the bottom to reset the stable id and reload the page. +This allows you to test different variations of the banners. + +If you deployed your own instance of this example you can also use the [Flags Explorer](https://vercel.com/docs/workflow-collaboration/feature-flags/using-vercel-toolbar) to test different variations by creating overrides. + +## Deploy this template + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fexamples%2Ftree%2Fmain%2Fflags-sdk%2Fflagsmith&env=FLAGS_SECRET&envDescription=The+FLAGS_SECRET+will+be+used+by+the+Flags+Explorer+to+securely+overwrite+feature+flags.+Must+be+32+random+bytes%2C+base64-encoded.+Use+the+generated+value+or+set+your+own.&envLink=https%3A%2F%2Fvercel.com%2Fdocs%2Fworkflow-collaboration%2Ffeature-flags%2Fsupporting-feature-flags%23flags_secret-environment-variable&project-name=flagsmith-flags-sdk-example&repository-name=flagsmith-flags-sdk-example) + +### Step 1: Link the project + +First, install the latest version of the Vercel CLI: + +```bash +pnpm i -g vercel +``` + +or + +```bash +npm i -g vercel +``` + +To use the Flags Explorer, you need to connect your local project to your Vercel project: + +```bash +vercel link +``` + +Select the project from the list you just deployed. + +### Step 2: Pull all environment variables + +This allows the Flags SDK and the Flags Explorer to work correctly, by getting additional metadata. + +```bash +vercel env pull +``` + +Step 3: Create Feature Flags +Head over to Flagsmith dashboard and create the feature flags required by this template. + +Feature Flags: + +Summer Sale with the key summer-sale +Free Shipping with the key free-delivery +Proceed To Checkout with the key proceed-to-checkout-color +You can also find the feature flag keys in the flags.ts file. + +Set both feature flags to rollout to 50% of users. diff --git a/flags-sdk/flagsmith/app/.well-known/vercel/flags/route.ts b/flags-sdk/flagsmith/app/.well-known/vercel/flags/route.ts new file mode 100644 index 000000000..50e934538 --- /dev/null +++ b/flags-sdk/flagsmith/app/.well-known/vercel/flags/route.ts @@ -0,0 +1,6 @@ +import { createFlagsDiscoveryEndpoint, getProviderData } from 'flags/next' +import * as flags from '../../../../flags' + +export const dynamic = 'force-dynamic' // defaults to auto + +export const GET = createFlagsDiscoveryEndpoint(() => getProviderData(flags)) diff --git a/flags-sdk/flagsmith/app/[code]/add-to-cart.tsx b/flags-sdk/flagsmith/app/[code]/add-to-cart.tsx new file mode 100644 index 000000000..c4d7c18bc --- /dev/null +++ b/flags-sdk/flagsmith/app/[code]/add-to-cart.tsx @@ -0,0 +1,30 @@ +'use client' + +import { track } from '@vercel/analytics' +import { useEffect, useState } from 'react' +import { useRouter } from 'next/navigation' +import { addToCart } from '@/lib/actions' +import { useProductDetailPageContext } from '@/components/utils/product-detail-page-context' +import { AddToCartButton } from '@/components/product-detail-page/add-to-cart-button' + +export function AddToCart() { + const router = useRouter() + const { color, size } = useProductDetailPageContext() + const [isLoading, setIsLoading] = useState(false) + + useEffect(() => { + track('add_to_cart:viewed') + }, []) + + return ( + { + setIsLoading(true) + track('add_to_cart:clicked') + await addToCart({ id: 'shirt', color, size, quantity: 1 }) + router.push('/cart') + }} + /> + ) +} diff --git a/flags-sdk/flagsmith/app/[code]/cart/order-summary.tsx b/flags-sdk/flagsmith/app/[code]/cart/order-summary.tsx new file mode 100644 index 000000000..f48456be9 --- /dev/null +++ b/flags-sdk/flagsmith/app/[code]/cart/order-summary.tsx @@ -0,0 +1,22 @@ +import { proceedToCheckoutColorFlag } from '@/flags' +import { OrderSummarySection } from '@/components/shopping-cart/order-summary-section' +import { ProceedToCheckout } from './proceed-to-checkout' + +export async function OrderSummary({ + showSummerBanner, + freeDelivery, +}: { + showSummerBanner: boolean + freeDelivery: boolean +}) { + // This is a fast feature flag so we don't suspend on it + const proceedToCheckoutColor = await proceedToCheckoutColorFlag() + + return ( + } + /> + ) +} diff --git a/flags-sdk/flagsmith/app/[code]/cart/page.tsx b/flags-sdk/flagsmith/app/[code]/cart/page.tsx new file mode 100644 index 000000000..90e562543 --- /dev/null +++ b/flags-sdk/flagsmith/app/[code]/cart/page.tsx @@ -0,0 +1,33 @@ +import { OrderSummary } from '@/app/[code]/cart/order-summary' +import { Main } from '@/components/main' +import { ShoppingCart } from '@/components/shopping-cart/shopping-cart' +import { + productFlags, + showFreeDeliveryBannerFlag, + showSummerBannerFlag, +} from '@/flags' + +export default async function CartPage({ + params, +}: { + params: Promise<{ code: string }> +}) { + const { code } = await params + const showSummerBanner = await showSummerBannerFlag(code, productFlags) + const freeDeliveryBanner = await showFreeDeliveryBannerFlag( + code, + productFlags + ) + + return ( +
+
+ + +
+
+ ) +} diff --git a/flags-sdk/flagsmith/app/[code]/cart/proceed-to-checkout.tsx b/flags-sdk/flagsmith/app/[code]/cart/proceed-to-checkout.tsx new file mode 100644 index 000000000..b5bedb0bb --- /dev/null +++ b/flags-sdk/flagsmith/app/[code]/cart/proceed-to-checkout.tsx @@ -0,0 +1,21 @@ +'use client' + +import { ProceedToCheckoutButton } from '@/components/shopping-cart/proceed-to-checkout-button' +import { track } from '@vercel/analytics' +import { toast } from 'sonner' + +export function ProceedToCheckout({ color }: { color: string }) { + return ( + { + track('proceed_to_checkout:clicked') + toast('End reached', { + className: 'my-classname', + description: 'The checkout flow is not implemented in this template.', + duration: 5000, + }) + }} + /> + ) +} diff --git a/flags-sdk/flagsmith/app/[code]/layout.tsx b/flags-sdk/flagsmith/app/[code]/layout.tsx new file mode 100644 index 000000000..c1e392465 --- /dev/null +++ b/flags-sdk/flagsmith/app/[code]/layout.tsx @@ -0,0 +1,45 @@ +import { deserialize, generatePermutations } from 'flags/next' +import { FlagValues } from 'flags/react' +import { productFlags, showFreeDeliveryBannerFlag } from '@/flags' +import { FreeDelivery } from '@/app/free-delivery' +import { DevTools } from '@/components/dev-tools' +import { Footer } from '@/components/footer' +import { Navigation } from '@/components/navigation' + +export async function generateStaticParams() { + // Returning an empty array here is important as it enables ISR, so + // the various combinations stay cached after they first time they were rendered. + // + // return []; + + // Instead of returning an empty array you could also call generatePermutations + // to generate the permutations upfront. + const codes = await generatePermutations(productFlags) + return codes.map((code) => ({ code })) +} + +export default async function Layout(props: { + children: React.ReactNode + params: Promise<{ + code: string + }> +}) { + const params = await props.params + const values = await deserialize(productFlags, params.code) + + const showFreeDeliveryBanner = await showFreeDeliveryBannerFlag( + params.code, + productFlags + ) + + return ( +
+ + + {props.children} + +
+ +
+ ) +} diff --git a/flags-sdk/flagsmith/app/[code]/page.tsx b/flags-sdk/flagsmith/app/[code]/page.tsx new file mode 100644 index 000000000..297799056 --- /dev/null +++ b/flags-sdk/flagsmith/app/[code]/page.tsx @@ -0,0 +1,38 @@ +import { SummerSale } from '@/app/summer-sale' +import { ImageGallery } from '@/components/image-gallery' +import { ProductDetails } from '@/components/product-detail-page/product-details' +import { ProductHeader } from '@/components/product-detail-page/product-header' +import { AddToCart } from '@/app/[code]/add-to-cart' +import { ColorPicker } from '@/components/product-detail-page/color-picker' +import { SizePicker } from '@/components/product-detail-page/size-picker' +import { ProductDetailPageProvider } from '@/components/utils/product-detail-page-context' + +import { productFlags, showSummerBannerFlag } from '@/flags' +import { Main } from '@/components/main' + +export default async function Page(props: { + params: Promise<{ code: string }> +}) { + const params = await props.params + + const showSummerBanner = await showSummerBannerFlag(params.code, productFlags) + + return ( + + +
+
+ + + +
+ + + + +
+
+
+
+ ) +} diff --git a/flags-sdk/flagsmith/app/favicon.ico b/flags-sdk/flagsmith/app/favicon.ico new file mode 100644 index 000000000..81d9b2da7 Binary files /dev/null and b/flags-sdk/flagsmith/app/favicon.ico differ diff --git a/flags-sdk/flagsmith/app/free-delivery.tsx b/flags-sdk/flagsmith/app/free-delivery.tsx new file mode 100644 index 000000000..efcd94297 --- /dev/null +++ b/flags-sdk/flagsmith/app/free-delivery.tsx @@ -0,0 +1,15 @@ +'use client' + +import { FreeDeliveryBanner } from '@/components/banners/free-delivery-banner' +import { track } from '@vercel/analytics' +import { useEffect } from 'react' + +export function FreeDelivery(props: { show: boolean }) { + useEffect(() => { + if (props.show) track('free_delivery_banner:viewed') + }, [props.show]) + + if (!props.show) return null + + return +} diff --git a/flags-sdk/flagsmith/app/globals.css b/flags-sdk/flagsmith/app/globals.css new file mode 100644 index 000000000..bf5ceb93f --- /dev/null +++ b/flags-sdk/flagsmith/app/globals.css @@ -0,0 +1,10 @@ +@import 'tailwindcss'; + +@custom-variant dark (&:is(.dark *)); + +@theme { + --color-link: rgb(0 112 243 / 1); + --color-success: rgb(0 112 243 / 1); + --color-background: white; + --color-success-dark: rgb(7 97 209 / 1); +} diff --git a/flags-sdk/flagsmith/app/layout.tsx b/flags-sdk/flagsmith/app/layout.tsx new file mode 100644 index 000000000..9ea0358e0 --- /dev/null +++ b/flags-sdk/flagsmith/app/layout.tsx @@ -0,0 +1,30 @@ +import { VercelToolbar } from '@vercel/toolbar/next' +import { Analytics } from '@vercel/analytics/next' +import type { Metadata } from 'next' +import { Toaster } from 'sonner' + +import './globals.css' +import { ExamplesBanner } from '@/components/banners/examples-banner' + +export const metadata: Metadata = { + title: 'Flags SDK Example', + description: 'A Flags SDK example for Ecommerce', +} + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode +}>) { + return ( + + + + {children} + + + + + + ) +} diff --git a/flags-sdk/flagsmith/app/summer-sale.tsx b/flags-sdk/flagsmith/app/summer-sale.tsx new file mode 100644 index 000000000..eae9c793b --- /dev/null +++ b/flags-sdk/flagsmith/app/summer-sale.tsx @@ -0,0 +1,27 @@ +'use client' + +import { track } from '@vercel/analytics' +import { useEffect } from 'react' +import { toast } from 'sonner' +import { SummerSaleBanner } from '@/components/banners/summer-sale-banner' + +export function SummerSale(props: { show: boolean }) { + useEffect(() => { + if (props.show) track('summer_banner:viewed') + }, [props.show]) + + if (!props.show) return null + + return ( + { + track('summer_banner:clicked') + toast('End reached', { + className: 'my-classname', + description: + 'The summer sale is not implemented in this template. Try adding to the cart instead.', + }) + }} + /> + ) +} diff --git a/flags-sdk/flagsmith/components/banners/examples-banner.tsx b/flags-sdk/flagsmith/components/banners/examples-banner.tsx new file mode 100644 index 000000000..408aafa77 --- /dev/null +++ b/flags-sdk/flagsmith/components/banners/examples-banner.tsx @@ -0,0 +1,77 @@ +import Link from 'next/link' + +export function ExamplesBanner() { + return ( + + ) +} diff --git a/flags-sdk/flagsmith/components/banners/free-delivery-banner.tsx b/flags-sdk/flagsmith/components/banners/free-delivery-banner.tsx new file mode 100644 index 000000000..810ba4a65 --- /dev/null +++ b/flags-sdk/flagsmith/components/banners/free-delivery-banner.tsx @@ -0,0 +1,7 @@ +export function FreeDeliveryBanner() { + return ( +
+ Get free delivery on orders over $30 +
+ ) +} diff --git a/flags-sdk/flagsmith/components/banners/summer-sale-banner.tsx b/flags-sdk/flagsmith/components/banners/summer-sale-banner.tsx new file mode 100644 index 000000000..2b36701d0 --- /dev/null +++ b/flags-sdk/flagsmith/components/banners/summer-sale-banner.tsx @@ -0,0 +1,41 @@ +'use client' + +import Image from 'next/image' +import pool from '@/public/images/pool.jpg' + +export function SummerSaleBanner({ onClick }: { onClick: () => void }) { + return ( +
+
+
+
+ Summer Sale +
+
+
+

+ Summer Sale +

+

+ Enjoy 20% off all summer basics, +
+ including swimwear and accessories. +

+ +
+
+
+
+
+ ) +} diff --git a/flags-sdk/flagsmith/components/dev-tools.tsx b/flags-sdk/flagsmith/components/dev-tools.tsx new file mode 100644 index 000000000..62f3d8076 --- /dev/null +++ b/flags-sdk/flagsmith/components/dev-tools.tsx @@ -0,0 +1,28 @@ +'use client' + +import { ArrowPathIcon } from '@heroicons/react/24/outline' +import { useRouter } from 'next/navigation' + +export function DevTools() { + const router = useRouter() + + const deleteCookie = () => { + document.cookie = + 'stable-id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;' + router.refresh() + } + + return ( +
+ Dev Tools + +
+ ) +} diff --git a/flags-sdk/flagsmith/components/footer.tsx b/flags-sdk/flagsmith/components/footer.tsx new file mode 100644 index 000000000..e9fcbef42 --- /dev/null +++ b/flags-sdk/flagsmith/components/footer.tsx @@ -0,0 +1,46 @@ +import { ShoppingBagIcon } from '@heroicons/react/24/outline' + +const navigation = [ + 'Home', + 'About', + 'Terms & Conditions', + 'Shipping & Return Policy', + 'Privacy Policy', + 'FAQ', +] + +export function Footer() { + return ( +
+
+
+
+
+ +
+ +
+
+ +
+
+
+
+ +
+

+ © {new Date().getFullYear()} ACME, Inc. All rights reserved. +

+
+
+
+ ) +} diff --git a/flags-sdk/flagsmith/components/image-gallery.tsx b/flags-sdk/flagsmith/components/image-gallery.tsx new file mode 100644 index 000000000..fdea05d9c --- /dev/null +++ b/flags-sdk/flagsmith/components/image-gallery.tsx @@ -0,0 +1,34 @@ +'use client' + +import { colorToImage, images } from '@/components/utils/images' +import { useProductDetailPageContext } from '@/components/utils/product-detail-page-context' +import clsx from 'clsx' +import Image from 'next/image' + +export function ImageGallery() { + const { color } = useProductDetailPageContext() + + const orderedImages = [...images].sort((a, b) => { + if (a === colorToImage[color]) return -1 + if (b === colorToImage[color]) return 1 + return 0 + }) + + return ( +
+
+ {orderedImages.map((image, index) => ( + Product Image + ))} +
+
+ ) +} diff --git a/flags-sdk/flagsmith/components/main.tsx b/flags-sdk/flagsmith/components/main.tsx new file mode 100644 index 000000000..5115fdd07 --- /dev/null +++ b/flags-sdk/flagsmith/components/main.tsx @@ -0,0 +1,7 @@ +export function Main({ children }: { children: React.ReactNode }) { + return ( +
+ {children} +
+ ) +} diff --git a/flags-sdk/flagsmith/components/navigation.tsx b/flags-sdk/flagsmith/components/navigation.tsx new file mode 100644 index 000000000..8ce2dc792 --- /dev/null +++ b/flags-sdk/flagsmith/components/navigation.tsx @@ -0,0 +1,76 @@ +import { getCart } from '@/lib/actions' +import { ShoppingBagIcon, ShoppingCartIcon } from '@heroicons/react/24/outline' +import Link from 'next/link' +import { Suspense } from 'react' + +const navigation = ['Home', 'Sale', 'New', 'Shirts', 'Stickers'] + +function ShoppingCartNavItemFallback() { + return ( + + + + + ) +} + +async function ShoppingCartNavItem() { + const cart = await getCart() + return ( + + + + {cart.items.reduce((acc, item) => acc + item.quantity, 0)} + + + ) +} + +export function Navigation() { + return ( +
+ +
+ ) +} diff --git a/flags-sdk/flagsmith/components/product-detail-page/add-to-cart-button.tsx b/flags-sdk/flagsmith/components/product-detail-page/add-to-cart-button.tsx new file mode 100644 index 000000000..c6942ff4b --- /dev/null +++ b/flags-sdk/flagsmith/components/product-detail-page/add-to-cart-button.tsx @@ -0,0 +1,55 @@ +'use client' + +import { motion, AnimatePresence } from 'framer-motion' + +function Spinner() { + return ( + + ) +} + +export function AddToCartButton({ + onClick, + isLoading, +}: { + onClick: () => {} + isLoading: boolean +}) { + return ( + + ) +} diff --git a/flags-sdk/flagsmith/components/product-detail-page/color-picker.tsx b/flags-sdk/flagsmith/components/product-detail-page/color-picker.tsx new file mode 100644 index 000000000..4af55d32e --- /dev/null +++ b/flags-sdk/flagsmith/components/product-detail-page/color-picker.tsx @@ -0,0 +1,49 @@ +'use client' + +import { useProductDetailPageContext } from '@/components/utils/product-detail-page-context' +import { Radio, RadioGroup } from '@headlessui/react' +import clsx from 'clsx' + +const colors = [ + { name: 'Black', bgColor: 'bg-gray-900', selectedColor: 'ring-gray-900' }, + { name: 'White', bgColor: 'bg-white', selectedColor: 'ring-gray-300' }, + { name: 'Blue', bgColor: 'bg-blue-500', selectedColor: 'ring-blue-500' }, +] + +export function ColorPicker() { + const { color, setColor } = useProductDetailPageContext() + const selectedColor = colors.find((c) => c.name === color) || colors[0] + + return ( +
+

Color

+
+ setColor(newColor.name)} + className="flex items-center gap-x-3" + > + {colors.map((color) => ( + + + ))} + +
+
+ ) +} diff --git a/flags-sdk/flagsmith/components/product-detail-page/product-details.tsx b/flags-sdk/flagsmith/components/product-detail-page/product-details.tsx new file mode 100644 index 000000000..097294f89 --- /dev/null +++ b/flags-sdk/flagsmith/components/product-detail-page/product-details.tsx @@ -0,0 +1,40 @@ +export function ProductDetails() { + return ( + <> +
+

Description

+
+

+ Embrace geometric simplicity with our Circles tee. This modern take + on casual wear features a clean, minimalist design that speaks + volumes without saying a word. Each circle pattern is perfectly + balanced, creating a visual rhythm that makes this tee both a + statement piece and a versatile wardrobe essential. +

+
+
+ +
+

+ Quality you can feel +

+
+
    +
  • + Premium-grade cotton blend for exceptional comfort +
  • +
  • + Pre-washed and pre-shrunk for a reliable fit +
  • +
  • + Proudly produced in local partner facilities +
  • +
+
+
+ + ) +} diff --git a/flags-sdk/flagsmith/components/product-detail-page/product-header.tsx b/flags-sdk/flagsmith/components/product-detail-page/product-header.tsx new file mode 100644 index 000000000..79099b84d --- /dev/null +++ b/flags-sdk/flagsmith/components/product-detail-page/product-header.tsx @@ -0,0 +1,13 @@ +import { ProductReviews } from './product-reviews' + +export function ProductHeader() { + return ( +
+
+

Circles T-Shirt

+

20.00 USD

+
+ +
+ ) +} diff --git a/flags-sdk/flagsmith/components/product-detail-page/product-reviews.tsx b/flags-sdk/flagsmith/components/product-detail-page/product-reviews.tsx new file mode 100644 index 000000000..46e14c7b8 --- /dev/null +++ b/flags-sdk/flagsmith/components/product-detail-page/product-reviews.tsx @@ -0,0 +1,27 @@ +import clsx from 'clsx' +import { StarIcon } from '@heroicons/react/20/solid' + +export function ProductReviews() { + return ( +
+
+

4.9

+
+ {[0, 1, 2, 3, 4].map((rating) => ( +
+ +
+ See all 312 reviews +
+
+
+ ) +} diff --git a/flags-sdk/flagsmith/components/product-detail-page/size-picker.tsx b/flags-sdk/flagsmith/components/product-detail-page/size-picker.tsx new file mode 100644 index 000000000..f818869cf --- /dev/null +++ b/flags-sdk/flagsmith/components/product-detail-page/size-picker.tsx @@ -0,0 +1,51 @@ +'use client' + +import { Radio, RadioGroup } from '@headlessui/react' +import clsx from 'clsx' +import { useProductDetailPageContext } from '@/components/utils/product-detail-page-context' + +const sizes = [ + { name: 'XXS', inStock: true }, + { name: 'XS', inStock: true }, + { name: 'S', inStock: true }, + { name: 'M', inStock: true }, + { name: 'L', inStock: true }, + { name: 'XL', inStock: false }, +] + +export function SizePicker() { + const { size, setSize } = useProductDetailPageContext() + const selectedSize = sizes.find((s) => s.name === size) || sizes[0] + + return ( +
+
+

Size

+
+ +
+ setSize(newSize.name)} + className="grid grid-cols-3 gap-3 sm:grid-cols-6" + > + {sizes.map((size) => ( + + {size.name} + + ))} + +
+
+ ) +} diff --git a/flags-sdk/flagsmith/components/shopping-cart/order-summary-section.tsx b/flags-sdk/flagsmith/components/shopping-cart/order-summary-section.tsx new file mode 100644 index 000000000..1a30f8f08 --- /dev/null +++ b/flags-sdk/flagsmith/components/shopping-cart/order-summary-section.tsx @@ -0,0 +1,127 @@ +import { getCart } from '@/lib/actions' +import Link from 'next/link' +import { Suspense } from 'react' + +function OrderSummaryFallback({ + showSummerBanner, +}: { + showSummerBanner: boolean +}) { + return ( +
+
+
+
+
+ {showSummerBanner ? ( +
+
+
+
+ ) : null} +
+
+
+
+
+
+
+
+
+ ) +} + +async function OrderSummaryContent({ + showSummerBanner, + freeDelivery, +}: { + showSummerBanner: boolean + freeDelivery: boolean +}) { + const { items } = await getCart() + const subtotal = items.length * 20 // Assuming $20 per shirt + const summerDiscount = showSummerBanner ? subtotal * (20 / 100) * -1 : 0 // 20% discount + const qualifyingForFreeDelivery = freeDelivery && subtotal > 30 + const shippingCost = 5 + const shipping = qualifyingForFreeDelivery ? 0 : shippingCost + const total = subtotal + shipping + summerDiscount + + return ( +
+
+

Subtotal

+

+ {subtotal.toFixed(2)} USD +

+
+ {showSummerBanner ? ( +
+

Summer discount

+

+ {summerDiscount.toFixed(2)} USD +

+
+ ) : null} +
+

Shipping estimate

+ {qualifyingForFreeDelivery ? ( +

+ + {shipping.toFixed(2)} USD + {' '} + FREE +

+ ) : ( +

+ {shipping.toFixed(2)} USD +

+ )} +
+
+

Order total

+

+ {total.toFixed(2)} USD +

+
+
+ ) +} + +export function OrderSummarySection({ + showSummerBanner, + freeDelivery, + proceedToCheckout, +}: { + showSummerBanner: boolean + freeDelivery: boolean + proceedToCheckout: React.ReactNode +}) { + return ( +
+

Order summary

+ +
{proceedToCheckout}
+ + } + > + + + +
+

+ or{' '} + + Continue Shopping + +

+
+
+ ) +} diff --git a/flags-sdk/flagsmith/components/shopping-cart/proceed-to-checkout-button.tsx b/flags-sdk/flagsmith/components/shopping-cart/proceed-to-checkout-button.tsx new file mode 100644 index 000000000..26034928b --- /dev/null +++ b/flags-sdk/flagsmith/components/shopping-cart/proceed-to-checkout-button.tsx @@ -0,0 +1,25 @@ +'use client' + +const colorMap: Record = { + blue: 'bg-blue-600 hover:bg-blue-700', + red: 'bg-red-600 hover:bg-red-700', + green: 'bg-green-600 hover:bg-green-700', +} + +export function ProceedToCheckoutButton({ + color, + onClick, +}: { + color: string + onClick: () => void +}) { + return ( + + ) +} diff --git a/flags-sdk/flagsmith/components/shopping-cart/shopping-cart-item.tsx b/flags-sdk/flagsmith/components/shopping-cart/shopping-cart-item.tsx new file mode 100644 index 000000000..e6597f284 --- /dev/null +++ b/flags-sdk/flagsmith/components/shopping-cart/shopping-cart-item.tsx @@ -0,0 +1,71 @@ +'use client' +import { CartItem } from '@/components/utils/cart-types' +import { ShoppingBagIcon } from '@heroicons/react/24/outline' +import { colorToImage } from '@/components/utils/images' +import { motion } from 'framer-motion' +import Image from 'next/image' +import { ShoppingCartRemoveButton } from './shopping-cart-remove-button' +import Link from 'next/link' + +export function EmptyShoppingCartItem() { + return ( + + Your cart is empty.{' '} + + Continue shopping + + + ) +} + +export function ShoppingCartItem({ item }: { item: CartItem }) { + return ( + +
+ {colorToImage[item.color] ? ( + {`${item.color} + ) : ( +
+ +
+ )} +
+ +
+
+
+

Circles T-Shirt

+

20.00 USD

+
+

+ {item.color}, {item.size} +

+
+
+

Qty {item.quantity}

+
+ +
+
+
+
+ ) +} diff --git a/flags-sdk/flagsmith/components/shopping-cart/shopping-cart-list.tsx b/flags-sdk/flagsmith/components/shopping-cart/shopping-cart-list.tsx new file mode 100644 index 000000000..b4b096b8e --- /dev/null +++ b/flags-sdk/flagsmith/components/shopping-cart/shopping-cart-list.tsx @@ -0,0 +1,13 @@ +'use client' + +import { AnimatePresence } from 'framer-motion' + +export function ShoppingCartList({ children }: { children: React.ReactNode }) { + return ( +
    + + {children} + +
+ ) +} diff --git a/flags-sdk/flagsmith/components/shopping-cart/shopping-cart-remove-button.tsx b/flags-sdk/flagsmith/components/shopping-cart/shopping-cart-remove-button.tsx new file mode 100644 index 000000000..77aa54815 --- /dev/null +++ b/flags-sdk/flagsmith/components/shopping-cart/shopping-cart-remove-button.tsx @@ -0,0 +1,49 @@ +'use client' + +import { removeFromCart } from '@/lib/actions' +import { motion, AnimatePresence } from 'framer-motion' +import { useState } from 'react' +import { CartItem } from '@/components/utils/cart-types' + +function Spinner() { + return ( + + ) +} + +export function ShoppingCartRemoveButton({ item }: { item: CartItem }) { + const [isLoading, setIsLoading] = useState(false) + return ( + + ) +} diff --git a/flags-sdk/flagsmith/components/shopping-cart/shopping-cart.tsx b/flags-sdk/flagsmith/components/shopping-cart/shopping-cart.tsx new file mode 100644 index 000000000..582871055 --- /dev/null +++ b/flags-sdk/flagsmith/components/shopping-cart/shopping-cart.tsx @@ -0,0 +1,65 @@ +import { getCart } from '@/lib/actions' +import { Suspense } from 'react' +import { ShoppingCartList } from './shopping-cart-list' +import { EmptyShoppingCartItem, ShoppingCartItem } from './shopping-cart-item' + +function ShoppingCartContentFallback() { + return ( +
    +
  • +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
  • +
+ ) +} + +async function ShoppingCartContent() { + const { items } = await getCart() + return ( + + {items.length === 0 ? ( + + ) : ( + items.map((item) => ( + + )) + )} + + ) +} + +export function ShoppingCart() { + return ( +
+
+

+ Shopping Cart +

+ +
+
+ }> + + +
+
+
+
+ ) +} diff --git a/flags-sdk/flagsmith/components/utils/cart-types.ts b/flags-sdk/flagsmith/components/utils/cart-types.ts new file mode 100644 index 000000000..5a66cf13b --- /dev/null +++ b/flags-sdk/flagsmith/components/utils/cart-types.ts @@ -0,0 +1,11 @@ +export interface CartItem { + id: string + color: string + size: string + quantity: number +} + +export interface Cart { + id: string + items: CartItem[] +} diff --git a/flags-sdk/flagsmith/components/utils/images.ts b/flags-sdk/flagsmith/components/utils/images.ts new file mode 100644 index 000000000..dd7bc890a --- /dev/null +++ b/flags-sdk/flagsmith/components/utils/images.ts @@ -0,0 +1,11 @@ +import blue from '@/public/images/product/shirt-blue.avif' +import black from '@/public/images/product/shirt-black.avif' +import white from '@/public/images/product/shirt-white.avif' + +export const images = [black, white, blue] + +export const colorToImage: Record = { + Black: black, + White: white, + Blue: blue, +} diff --git a/flags-sdk/flagsmith/components/utils/product-detail-page-context.tsx b/flags-sdk/flagsmith/components/utils/product-detail-page-context.tsx new file mode 100644 index 000000000..b869a03fe --- /dev/null +++ b/flags-sdk/flagsmith/components/utils/product-detail-page-context.tsx @@ -0,0 +1,49 @@ +'use client' + +import { createContext, useContext, useMemo, useState } from 'react' + +export type ProductDetailPageContextType = { + color: string + size: string + setColor: (color: string) => void + setSize: (size: string) => void +} + +export function useProductDetailPageContext(): ProductDetailPageContextType { + return useContext(ProductDetailPageContext) +} + +export const ProductDetailPageContext = + createContext({ + color: 'Black', + size: 'S', + setColor: () => {}, + setSize: () => {}, + }) + +export function ProductDetailPageProvider({ + children, +}: { + children: React.ReactNode +}) { + const [state, setState] = useState({ + color: 'Black', + size: 'S', + }) + + const context = useMemo( + () => ({ + color: state.color, + size: state.size, + setColor: (color: string) => setState({ ...state, color }), + setSize: (size: string) => setState({ ...state, size }), + }), + [state] + ) + + return ( + + {children} + + ) +} diff --git a/flags-sdk/flagsmith/flags.ts b/flags-sdk/flagsmith/flags.ts new file mode 100644 index 000000000..7ac046c2e --- /dev/null +++ b/flags-sdk/flagsmith/flags.ts @@ -0,0 +1,53 @@ +import { flag } from 'flags/next' +import { identify } from './lib/identify' +import { flagsmithAdapter } from '@flags-sdk/flagsmith' +import { IIdentity } from '@flags-sdk/flagsmith' + + +export const showSummerBannerFlag = flag({ + key: 'summer-sale', + description: 'Shows a bright yellow banner for a 20% discount', + defaultValue: false, + adapter: flagsmithAdapter.booleanValue(), + identify, +}) + +export const showFreeDeliveryBannerFlag = flag({ + key: 'free-delivery', + description: 'Show a black free delivery banner at the top of the page', + defaultValue: false, + identify, + adapter: flagsmithAdapter.booleanValue(), +}) + +export const proceedToCheckoutColorFlag = flag({ + key: 'proceed-to-checkout-color', + description: 'The color of the proceed to checkout button', + defaultValue: 'blue', + options: ['blue', 'green', 'red'], + identify, + adapter: flagsmithAdapter.stringValue(), +}) + +export const delayFlag = flag({ + key: 'delay', + defaultValue: 0, + description: + 'A flag for debugging and demo purposes which delays the data loading', + options: [ + { value: 0, label: 'No delay' }, + { value: 200, label: '200ms' }, + { value: 1000, label: '1s' }, + { value: 3000, label: '3s' }, + { value: 10_000, label: '10s' }, + ], + decide() { + return this.defaultValue as number + }, +}) + +export const productFlags = [ + showFreeDeliveryBannerFlag, + showSummerBannerFlag, + proceedToCheckoutColorFlag, +] as const diff --git a/flags-sdk/flagsmith/lib/actions.ts b/flags-sdk/flagsmith/lib/actions.ts new file mode 100644 index 000000000..deb694df1 --- /dev/null +++ b/flags-sdk/flagsmith/lib/actions.ts @@ -0,0 +1,44 @@ +'use server' + +import { revalidatePath } from 'next/cache' +import type { Cart, CartItem } from '@/components/utils/cart-types' +import { delayFlag } from '@/flags' +import { getCartId } from './get-cart-id' + +// Using a fallback here so we don't need to make the BACKEND_URL part of the env, +// which makes using the template easy.. +const BACKEND_URL = + process.env.BACKEND_URL || 'https://shirt-shop-api.labs.vercel.dev' + +export async function delay(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +export async function getCart(): Promise { + const cartId = await getCartId() + const delayMs = await delayFlag() + await delay(delayMs) + return fetch(`${BACKEND_URL}/api/cart/${cartId.value}`).then((res) => + res.json() + ) +} + +export async function addToCart(item: CartItem) { + const cartId = await getCartId() + await fetch(`${BACKEND_URL}/api/cart/${cartId.value}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(item), + }) + revalidatePath('/cart') +} + +export async function removeFromCart(item: CartItem) { + const cartId = await getCartId() + await fetch(`${BACKEND_URL}/api/cart/${cartId.value}`, { + method: 'DELETE', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(item), + }) + revalidatePath('/cart') +} diff --git a/flags-sdk/flagsmith/lib/get-cart-id.ts b/flags-sdk/flagsmith/lib/get-cart-id.ts new file mode 100644 index 000000000..deff8f73e --- /dev/null +++ b/flags-sdk/flagsmith/lib/get-cart-id.ts @@ -0,0 +1,21 @@ +import { cookies, headers } from 'next/headers' +import { dedupe } from 'flags/next' +import { nanoid } from 'nanoid' + +/** + * Reads the cart id from the cookie or returns a new cart id + */ +export const getCartId = dedupe(async () => { + const cookiesStore = await cookies() + const header = await headers() + + const generatedCartId = header.get('x-generated-cart-id') + + if (generatedCartId) { + return { value: generatedCartId, isFresh: false } + } + + const cartId = cookiesStore.get('cart-id')?.value + if (!cartId) return { value: nanoid(), isFresh: true } + return { value: cartId, isFresh: false } +}) diff --git a/flags-sdk/flagsmith/lib/get-stable-id.ts b/flags-sdk/flagsmith/lib/get-stable-id.ts new file mode 100644 index 000000000..744be9329 --- /dev/null +++ b/flags-sdk/flagsmith/lib/get-stable-id.ts @@ -0,0 +1,21 @@ +import { cookies, headers } from 'next/headers' +import { dedupe } from 'flags/next' +import { nanoid } from 'nanoid' + +/** + * Reads the stable id from the cookie or returns a new stable id + */ +export const getStableId = dedupe(async () => { + const cookiesStore = await cookies() + const header = await headers() + + const generatedStableId = header.get('x-generated-stable-id') + + if (generatedStableId) { + return { value: generatedStableId, isFresh: false } + } + + const stableId = cookiesStore.get('stable-id')?.value + if (!stableId) return { value: nanoid(), isFresh: true } + return { value: stableId, isFresh: false } +}) diff --git a/flags-sdk/flagsmith/lib/identify.ts b/flags-sdk/flagsmith/lib/identify.ts new file mode 100644 index 000000000..4cddc4bc0 --- /dev/null +++ b/flags-sdk/flagsmith/lib/identify.ts @@ -0,0 +1,11 @@ +import type { Identify } from 'flags' +import { dedupe } from 'flags/next' +import { getStableId } from './get-stable-id' +import type { EntitiesType } from '@flags-sdk/flagsmith' + +export const identify: Identify = dedupe( + async (): Promise => { + const stableId = await getStableId() + return stableId.value + } +) \ No newline at end of file diff --git a/flags-sdk/flagsmith/middleware.ts b/flags-sdk/flagsmith/middleware.ts new file mode 100644 index 000000000..980a1aa7c --- /dev/null +++ b/flags-sdk/flagsmith/middleware.ts @@ -0,0 +1,37 @@ +import { type NextRequest, NextResponse } from 'next/server' +import { precompute } from 'flags/next' +import { productFlags } from '@/flags' +import { getStableId } from './lib/get-stable-id' +import { getCartId } from './lib/get-cart-id' + +export const config = { + matcher: ['/', '/cart'], +} + +export async function middleware(request: NextRequest) { + const stableId = await getStableId() + const cartId = await getCartId() + const code = await precompute(productFlags) + + // rewrites the request to the variant for this flag combination + const nextUrl = new URL( + `/${code}${request.nextUrl.pathname}${request.nextUrl.search}`, + request.url + ) + + // Add a header to the request to indicate that the stable id is generated, + // as it will not be present on the cookie request header on the first-ever request. + if (cartId.isFresh) { + request.headers.set('x-generated-cart-id', cartId.value) + } + + if (stableId.isFresh) { + request.headers.set('x-generated-stable-id', stableId.value) + } + + // response headers + const headers = new Headers() + headers.append('set-cookie', `stable-id=${stableId.value}`) + headers.append('set-cookie', `cart-id=${cartId.value}`) + return NextResponse.rewrite(nextUrl, { request, headers }) +} diff --git a/flags-sdk/flagsmith/next.config.mjs b/flags-sdk/flagsmith/next.config.mjs new file mode 100644 index 000000000..dbf25b8c8 --- /dev/null +++ b/flags-sdk/flagsmith/next.config.mjs @@ -0,0 +1,11 @@ +// eslint-disable-next-line import/no-unresolved -- unsure +import withVercelToolbar from '@vercel/toolbar/plugins/next'; + +/** @type {import('next').NextConfig} */ +const nextConfig = { + experimental: { + ppr: 'incremental', + }, +}; + +export default withVercelToolbar()(nextConfig); diff --git a/flags-sdk/flagsmith/package.json b/flags-sdk/flagsmith/package.json new file mode 100644 index 000000000..bc6268f1e --- /dev/null +++ b/flags-sdk/flagsmith/package.json @@ -0,0 +1,42 @@ +{ + "name": "flags-sdk-openfeature-example", + "version": "0.0.0", + "private": true, + "scripts": { + "build": "next build", + "dev": "next dev", + "lint": "next lint", + "start": "next start" + }, + "dependencies": { + "@flags-sdk/flagsmith": "^1.0.0", + "@headlessui/react": "^2.2.0", + "@heroicons/react": "2.2.0", + "flagsmith": "^9.2.2", + "@tailwindcss/aspect-ratio": "0.4.2", + "@tailwindcss/forms": "0.5.10", + "@tailwindcss/postcss": "^4.0.9", + "@tailwindcss/typography": "0.5.16", + "@vercel/analytics": "1.5.0", + "@vercel/edge": "1.2.1", + "@vercel/toolbar": "0.1.33", + "clsx": "2.1.1", + "flags": "4.0.0", + "framer-motion": "12.4.7", + "js-xxhash": "4.0.0", + "nanoid": "5.1.2", + "next": "15.2.2-canary.4", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "sonner": "2.0.1" + }, + "devDependencies": { + "@types/node": "^22.13.5", + "@types/react": "^19.0.10", + "@types/react-dom": "^19.0.4", + "eslint": "^9.21.0", + "postcss": "^8.5.3", + "tailwindcss": "^4.0.9", + "typescript": "^5.7.3" + } +} diff --git a/flags-sdk/flagsmith/pnpm-lock.yaml b/flags-sdk/flagsmith/pnpm-lock.yaml new file mode 100644 index 000000000..55ad1b215 --- /dev/null +++ b/flags-sdk/flagsmith/pnpm-lock.yaml @@ -0,0 +1,2595 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@flags-sdk/flagsmith': + specifier: link:../../../../flags/packages/adapter-flagsmith + version: link:../../../../flags/packages/adapter-flagsmith + '@headlessui/react': + specifier: ^2.2.0 + version: 2.2.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@heroicons/react': + specifier: 2.2.0 + version: 2.2.0(react@19.0.0) + '@tailwindcss/aspect-ratio': + specifier: 0.4.2 + version: 0.4.2(tailwindcss@4.0.15) + '@tailwindcss/forms': + specifier: 0.5.10 + version: 0.5.10(tailwindcss@4.0.15) + '@tailwindcss/postcss': + specifier: ^4.0.9 + version: 4.0.15 + '@tailwindcss/typography': + specifier: 0.5.16 + version: 0.5.16(tailwindcss@4.0.15) + '@vercel/analytics': + specifier: 1.5.0 + version: 1.5.0(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0) + '@vercel/edge': + specifier: 1.2.1 + version: 1.2.1 + '@vercel/toolbar': + specifier: 0.1.33 + version: 0.1.33(@vercel/analytics@1.5.0(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0))(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + clsx: + specifier: 2.1.1 + version: 2.1.1 + flags: + specifier: 4.0.0 + version: 4.0.0(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + flagsmith: + specifier: ^9.2.2 + version: 9.2.2 + framer-motion: + specifier: 12.4.7 + version: 12.4.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + js-xxhash: + specifier: 4.0.0 + version: 4.0.0 + nanoid: + specifier: 5.1.2 + version: 5.1.2 + next: + specifier: 15.2.2-canary.4 + version: 15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: + specifier: ^19.0.0 + version: 19.0.0 + react-dom: + specifier: ^19.0.0 + version: 19.0.0(react@19.0.0) + sonner: + specifier: 2.0.1 + version: 2.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + devDependencies: + '@types/node': + specifier: ^22.13.5 + version: 22.13.11 + '@types/react': + specifier: ^19.0.10 + version: 19.0.12 + '@types/react-dom': + specifier: ^19.0.4 + version: 19.0.4(@types/react@19.0.12) + eslint: + specifier: ^9.21.0 + version: 9.22.0(jiti@2.4.2) + postcss: + specifier: ^8.5.3 + version: 8.5.3 + tailwindcss: + specifier: ^4.0.9 + version: 4.0.15 + typescript: + specifier: ^5.7.3 + version: 5.8.2 + +packages: + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@edge-runtime/cookies@5.0.2': + resolution: {integrity: sha512-Sd8LcWpZk/SWEeKGE8LT6gMm5MGfX/wm+GPnh1eBEtCpya3vYqn37wYknwAHw92ONoyyREl1hJwxV/Qx2DWNOg==} + engines: {node: '>=16'} + + '@emnapi/runtime@1.3.1': + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} + + '@eslint-community/eslint-utils@4.5.1': + resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.19.2': + resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.1.0': + resolution: {integrity: sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.12.0': + resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.0': + resolution: {integrity: sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.22.0': + resolution: {integrity: sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.7': + resolution: {integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@floating-ui/core@1.6.9': + resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==} + + '@floating-ui/dom@1.6.13': + resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==} + + '@floating-ui/react-dom@2.1.2': + resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/react@0.26.28': + resolution: {integrity: sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/utils@0.2.9': + resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} + + '@headlessui/react@2.2.0': + resolution: {integrity: sha512-RzCEg+LXsuI7mHiSomsu/gBJSjpupm6A1qIZ5sWjd7JhARNlMiSA4kKfJpCKwU9tE+zMRterhhrP74PvfJrpXQ==} + engines: {node: '>=10'} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + react-dom: ^18 || ^19 || ^19.0.0-rc + + '@heroicons/react@2.2.0': + resolution: {integrity: sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==} + peerDependencies: + react: '>= 16 || ^19.0.0-rc' + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.2': + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} + engines: {node: '>=18.18'} + + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@next/env@15.2.2-canary.4': + resolution: {integrity: sha512-m4jjOoJwFv6bmGq1KiAT6me8pkIvjPA6qWc1aRyUxzVzg/7Pm3b5BP2ze8jNwdjIwPmMQGtV0Lv50vLeDUlC0A==} + + '@next/swc-darwin-arm64@15.2.2-canary.4': + resolution: {integrity: sha512-NI4UlAkBsnUXT8KDI0tncL6pGqmYY7uhQhghxhulBADO44wNn6Ktg7HLky9NOz2NnTB54XUcITN3IJ7g7LsfAw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-x64@15.2.2-canary.4': + resolution: {integrity: sha512-r41aXyIdLe7kM2GZDRpxdO8EmwGykV9MNY1JxZgI09ON+3j/0+jd89IhtJauWWlPdUgAkJtJ2HJ6a0oCycHbRw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-linux-arm64-gnu@15.2.2-canary.4': + resolution: {integrity: sha512-WCvmjDAPuiFsmpfamn6taJYvqBjYwzRPCw6ZfYNxmsDYU84em70KL9HmNe72jTfOa95IK5u7JROyg7k3t5LvqA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-arm64-musl@15.2.2-canary.4': + resolution: {integrity: sha512-22LJu9qVTgyYrzv4J8H00OQ/jgJHZiH676FMhzvgkncyISPeMFq56ZrH2gu98Ifv57AV2l78aHPGCMS/vad3UA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-x64-gnu@15.2.2-canary.4': + resolution: {integrity: sha512-EjEIwHcldoJgiuwYTiaXI/H/B+U3FkNac552aPWQF9Up97fJwOiEEDaaBR9q/+b7KU4Qlr/l1XlfRJz+s/DeeA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-linux-x64-musl@15.2.2-canary.4': + resolution: {integrity: sha512-Vfs+HDa3W+y9lXYnGxYIyu9JHYwKQVDmweXULACMxDVyEicrKyRlcsdn97yRzoccMbDUjOlCgBYn8Hw0191oqA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-win32-arm64-msvc@15.2.2-canary.4': + resolution: {integrity: sha512-otcVJ2p66X1RrXqj+l6mJRXNNYUnSbEJTOHXgq4IKbvxbO1MsiXF/43jRo1O3kcwl8XmkMVlJgpsjOhooCf4Sg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-x64-msvc@15.2.2-canary.4': + resolution: {integrity: sha512-mt3OtYuIK8HqON//39UP5SRwDxCFv7+P3zgpMoYC+nJGivraAlGkloQJnx1vVA5QNbUtuCvgwnyPZYPSGVisvA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@react-aria/focus@3.20.1': + resolution: {integrity: sha512-lgYs+sQ1TtBrAXnAdRBQrBo0/7o5H6IrfDxec1j+VRpcXL0xyk0xPq+m3lZp8typzIghqDgpnKkJ5Jf4OrzPIw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-aria/interactions@3.24.1': + resolution: {integrity: sha512-OWEcIC6UQfWq4Td5Ptuh4PZQ4LHLJr/JL2jGYvuNL6EgL3bWvzPrRYIF/R64YbfVxIC7FeZpPSkS07sZ93/NoA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-aria/ssr@3.9.7': + resolution: {integrity: sha512-GQygZaGlmYjmYM+tiNBA5C6acmiDWF52Nqd40bBp0Znk4M4hP+LTmI0lpI1BuKMw45T8RIhrAsICIfKwZvi2Gg==} + engines: {node: '>= 12'} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-aria/utils@3.28.1': + resolution: {integrity: sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-stately/flags@3.1.0': + resolution: {integrity: sha512-KSHOCxTFpBtxhIRcKwsD1YDTaNxFtCYuAUb0KEihc16QwqZViq4hasgPBs2gYm7fHRbw7WYzWKf6ZSo/+YsFlg==} + + '@react-stately/utils@3.10.5': + resolution: {integrity: sha512-iMQSGcpaecghDIh3mZEpZfoFH3ExBwTtuBEcvZ2XnGzCgQjeYXcMdIUwAfVQLXFTdHUHGF6Gu6/dFrYsCzySBQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@react-types/shared@3.28.0': + resolution: {integrity: sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/helpers@0.5.15': + resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + + '@tailwindcss/aspect-ratio@0.4.2': + resolution: {integrity: sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==} + peerDependencies: + tailwindcss: '>=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1' + + '@tailwindcss/forms@0.5.10': + resolution: {integrity: sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==} + peerDependencies: + tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1' + + '@tailwindcss/node@4.0.15': + resolution: {integrity: sha512-IODaJjNmiasfZX3IoS+4Em3iu0fD2HS0/tgrnkYfW4hyUor01Smnr5eY3jc4rRgaTDrJlDmBTHbFO0ETTDaxWA==} + + '@tailwindcss/oxide-android-arm64@4.0.15': + resolution: {integrity: sha512-EBuyfSKkom7N+CB3A+7c0m4+qzKuiN0WCvzPvj5ZoRu4NlQadg/mthc1tl5k9b5ffRGsbDvP4k21azU4VwVk3Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.0.15': + resolution: {integrity: sha512-ObVAnEpLepMhV9VoO0JSit66jiN5C4YCqW3TflsE9boo2Z7FIjV80RFbgeL2opBhtxbaNEDa6D0/hq/EP03kgQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.0.15': + resolution: {integrity: sha512-IElwoFhUinOr9MyKmGTPNi1Rwdh68JReFgYWibPWTGuevkHkLWKEflZc2jtI5lWZ5U9JjUnUfnY43I4fEXrc4g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.0.15': + resolution: {integrity: sha512-6BLLqyx7SIYRBOnTZ8wgfXANLJV5TQd3PevRJZp0vn42eO58A2LykRKdvL1qyPfdpmEVtF+uVOEZ4QTMqDRAWA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.15': + resolution: {integrity: sha512-Zy63EVqO9241Pfg6G0IlRIWyY5vNcWrL5dd2WAKVJZRQVeolXEf1KfjkyeAAlErDj72cnyXObEZjMoPEKHpdNw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.0.15': + resolution: {integrity: sha512-2NemGQeaTbtIp1Z2wyerbVEJZTkAWhMDOhhR5z/zJ75yMNf8yLnE+sAlyf6yGDNr+1RqvWrRhhCFt7i0CIxe4Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.0.15': + resolution: {integrity: sha512-342GVnhH/6PkVgKtEzvNVuQ4D+Q7B7qplvuH20Cfz9qEtydG6IQczTZ5IT4JPlh931MG1NUCVxg+CIorr1WJyw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.0.15': + resolution: {integrity: sha512-g76GxlKH124RuGqacCEFc2nbzRl7bBrlC8qDQMiUABkiifDRHOIUjgKbLNG4RuR9hQAD/MKsqZ7A8L08zsoBrw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.0.15': + resolution: {integrity: sha512-Gg/Y1XrKEvKpq6WeNt2h8rMIKOBj/W3mNa5NMvkQgMC7iO0+UNLrYmt6zgZufht66HozNpn+tJMbbkZ5a3LczA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-win32-arm64-msvc@4.0.15': + resolution: {integrity: sha512-7QtSSJwYZ7ZK1phVgcNZpuf7c7gaCj8Wb0xjliligT5qCGCp79OV2n3SJummVZdw4fbTNKUOYMO7m1GinppZyA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.0.15': + resolution: {integrity: sha512-JQ5H+5MLhOjpgNp6KomouE0ZuKmk3hO5h7/ClMNAQ8gZI2zkli3IH8ZqLbd2DVfXDbdxN2xvooIEeIlkIoSCqw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.0.15': + resolution: {integrity: sha512-e0uHrKfPu7JJGMfjwVNyt5M0u+OP8kUmhACwIRlM+JNBuReDVQ63yAD1NWe5DwJtdaHjugNBil76j+ks3zlk6g==} + engines: {node: '>= 10'} + + '@tailwindcss/postcss@4.0.15': + resolution: {integrity: sha512-qyrpoDKIO7wzkRbKCvGLo7gXRjT9/Njf7ZJiJhG4njrfZkvOhjwnaHpYbpxYeDysEg+9pB1R4jcd+vQ7ZUDsmQ==} + + '@tailwindcss/typography@0.5.16': + resolution: {integrity: sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' + + '@tanstack/react-virtual@3.13.4': + resolution: {integrity: sha512-jPWC3BXvVLHsMX67NEHpJaZ+/FySoNxFfBEiF4GBc1+/nVwdRm+UcSCYnKP3pXQr0eEsDpXi/PQZhNfJNopH0g==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@tanstack/virtual-core@3.13.4': + resolution: {integrity: sha512-fNGO9fjjSLns87tlcto106enQQLycCKR4DPNpgq3djP5IdcPFdPAmaKjsgzIeRhH7hWrELgW12hYnRthS5kLUw==} + + '@tinyhttp/accepts@1.3.0': + resolution: {integrity: sha512-YaJ4EMgVUI6JHzWO14lr6vn/BLJEoFN4Sqd20l0/oBcLLENkP8gnPtX1jB7OhIu0AE40VCweAqvSP+0/pgzB1g==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/app@1.3.0': + resolution: {integrity: sha512-EPqdanEZ/vhpuxl4Nn/QIkS+5Wkbt8NgO/FqYj2kHttvwYkaoSFi7HUns17UQAQcak5JLbPEt67Qf4wvwy/fNQ==} + engines: {node: '>=12.x'} + + '@tinyhttp/content-disposition@1.3.0': + resolution: {integrity: sha512-sSj7YDVz7NcHDn6/O/I3WjtC8ZWJKKIGULoV+pgrLvJvtXK5WroE1Fm8rHRQewh2d9NMajh/7NX6NuSlF8LUaQ==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/cookie-signature@1.3.0': + resolution: {integrity: sha512-xCQZyCT1S/Rn2Z3SX2gp4IDAwW9AUnjky6hKvqzmMaQqEbIk7e2GCOXW5yjndbfGNTJAxj0tuLNMF4G8aLkfMw==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/cookie@1.3.0': + resolution: {integrity: sha512-4ZVfP8WApV9ZRchv/1i0QiKdP0wxWTUNv4ZsMQrqK0p1KXA0/SvpYUTS6bp1E6Yo0dNxcKte4wJ4FCWFDcShhQ==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/encode-url@0.3.0': + resolution: {integrity: sha512-QM5j5t0GLucBuBePoOilcz1/zDpqX+LtUdtkPn7IvoHTNJYNxEfSUmIMPUPhyVY7mvbwvafPUCK8u1Byx0+NfQ==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/etag@1.3.0': + resolution: {integrity: sha512-aWnDb4NuMf/UTm1H88rZgqu32E6t3iDHSHtAppiQCH4M7jRfTUEpiZjz//S+giDnOxAuYttLrXQ1+HGpgzyYUQ==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/forwarded@1.3.0': + resolution: {integrity: sha512-U2FPtOH+DoFtd98edMRyqiquRaiuEl5I2PMUWdKaBSpiAIR96buyanQ7hScenz1MihK0AVid7wLAviaJU+Xlyg==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/proxy-addr@1.3.0': + resolution: {integrity: sha512-7Kv6YIC/PlhUwyqAGXhg4DoQDOzbYlcGPkNv/KZAMFj9fZ6IEZyneyaClnD21hMT8qa7g3Z/66hxLa/WxiPAYA==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/req@1.3.0': + resolution: {integrity: sha512-zIbtJA7Hp2p4MqszP2jOBi2NWi8fTGd4lso+0CjwJa+WTE+lgXVAy6mN12rTAxjXweAyRvQpRIJ5W2r8OLuEXQ==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/res@1.3.0': + resolution: {integrity: sha512-ez6fCpGsYoU6HUBq0e+m4l6Cffu2FeucK+m5Z6a8sBGqLR7/teB1pFufCOPwrdwzdNrLNarGJpsNQpvQqDMWaA==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/router@1.3.0': + resolution: {integrity: sha512-I2HDtMq7WM4E1JfLyllJp+IAp3Hc0xLetfgi8d1TQkhms8/XC9ZhgOIlimc3//ncMZSIxofkj7TpDCdEd6M/eQ==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/send@1.3.0': + resolution: {integrity: sha512-3Tn8NaLhNdcIJQqc/3ZBFV0hX6jCaFNDX5/vWxoPubDrh8HOpn2foPXL7ZIRk8GDkaB/M3cSzKIlKpnTKmh0Nw==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/type-is@1.3.0': + resolution: {integrity: sha512-3NClOYPNJst9vVLcb793epRI+ZuRwl6IjxSq9LkGN8TEBbtNgv2vTmXZRWcUs2zY9Ju+NQIYecWcsG0Kx23E+g==} + engines: {node: '>=12.4.0'} + + '@tinyhttp/url@1.3.0': + resolution: {integrity: sha512-GgdKez5AaQRIm0kFNp7BZnxFQ2F7LZ7g3rOQ/v11oYZR3jhH7JPGM+7hZQjYqFXD/5TK/of7hepu418K2fghvg==} + engines: {node: '>=12.4.0'} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@22.13.11': + resolution: {integrity: sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g==} + + '@types/react-dom@19.0.4': + resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==} + peerDependencies: + '@types/react': ^19.0.0 + + '@types/react@19.0.12': + resolution: {integrity: sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==} + + '@vercel/analytics@1.5.0': + resolution: {integrity: sha512-MYsBzfPki4gthY5HnYN7jgInhAZ7Ac1cYDoRWFomwGHWEX7odTEzbtg9kf/QSo7XEsEAqlQugA6gJ2WS2DEa3g==} + peerDependencies: + '@remix-run/react': ^2 + '@sveltejs/kit': ^1 || ^2 + next: '>= 13' + react: ^18 || ^19 || ^19.0.0-rc + svelte: '>= 4' + vue: ^3 + vue-router: ^4 + peerDependenciesMeta: + '@remix-run/react': + optional: true + '@sveltejs/kit': + optional: true + next: + optional: true + react: + optional: true + svelte: + optional: true + vue: + optional: true + vue-router: + optional: true + + '@vercel/edge@1.2.1': + resolution: {integrity: sha512-1++yncEyIAi68D3UEOlytYb1IUcIulMWdoSzX2h9LuSeeyR7JtaIgR8DcTQ6+DmYOQn+5MCh6LY+UmK6QBByNA==} + + '@vercel/microfrontends@1.0.0': + resolution: {integrity: sha512-83ikhvV/k9F48zu/J7KtIi6ly1hZ5vSAosBBdkb9hmFgz8iL7iifjEpNp9cREjYa/8hajpbuVhqzsL23Cc+70Q==} + hasBin: true + peerDependencies: + '@vercel/analytics': '>=1.5.0' + '@vercel/speed-insights': '>=1.2.0' + next: '>=13' + react: '>=17.0.0' + react-dom: '>=17.0.0' + peerDependenciesMeta: + '@vercel/analytics': + optional: true + '@vercel/speed-insights': + optional: true + next: + optional: true + react: + optional: true + react-dom: + optional: true + + '@vercel/toolbar@0.1.33': + resolution: {integrity: sha512-92NzgxXRwiQ1frekzrTDFl93uslB5f9PT9QOeduLB9VHhThJ49OdRsddJgsVGJ4oW31EeOpCVyap3tHpA1sWzA==} + peerDependencies: + next: '>=11.0.0' + react: '>=17' + vite: '>=5' + peerDependenciesMeta: + next: + optional: true + react: + optional: true + vite: + optional: true + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001706: + resolution: {integrity: sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + 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@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + cookie@0.4.0: + resolution: {integrity: sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==} + engines: {node: '>= 0.6'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + + es-content-type@0.0.10: + resolution: {integrity: sha512-yCgcv1M2IuFUoGZ3zE4OR2INGmZOwEuyaE5WX4MOKGpJcO8JXgVOIcXVicwnTqlxvx6qs9IJGl/Rr1+YtCkRgg==} + engines: {node: '>=12.x'} + + es-fresh@0.0.8: + resolution: {integrity: sha512-ZM+K/T/zHJVuOhaz19iymidACazB1fl2uihBtSfRie8YzN1YM+KldVmNaU+GSmVvTOPSO2utKOhxcOinr5tKjw==} + engines: {node: '>=12.x'} + + es-mime-types@0.0.16: + resolution: {integrity: sha512-84QoSLeA7cdTeHpALFNl3ZOstXfvLt426/kaOgmSxmNUOhi4GesKVkhJgIfnsqGNziYezVA8rvZUsXj7oWX2qQ==} + engines: {node: '>=12.x'} + + es-vary@0.0.8: + resolution: {integrity: sha512-fiERjQiCHrXUAToNRT/sh7MtXnfei9n7cF9oVQRUEp9L5BGXsTKSPaXq8L+4v0c/ezfvuTWd/f0JSl5IBRUvSg==} + engines: {node: '>=12.x'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + 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} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.22.0: + resolution: {integrity: sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.0.6: + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flags@4.0.0: + resolution: {integrity: sha512-CpONOK/nflKfaTT36r+Y4SP5rb9mv3AdqY/2Ws+TScrEGlT4PK+PZNiKJgIH87HooTXDblz31807q7lZ3LpuYQ==} + peerDependencies: + '@opentelemetry/api': ^1.7.0 + '@sveltejs/kit': '*' + next: '*' + react: '*' + react-dom: '*' + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@sveltejs/kit': + optional: true + next: + optional: true + react: + optional: true + react-dom: + optional: true + + flagsmith@9.2.2: + resolution: {integrity: sha512-9UNI5Rdtv4r3rEruT3sLinZDKH1o7co8kSopmGDB5q9fCWHXLa1HLbjAwe9xPoMtWMpdS8gqLdY2UZBdfxuVdg==} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + framer-motion@12.4.7: + resolution: {integrity: sha512-VhrcbtcAMXfxlrjeHPpWVu2+mkcoR31e02aNSR7OUS/hZAciKa8q6o3YN2mA1h+jjscRsSyKvX6E1CiY/7OLMw==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + get-port@5.1.1: + resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} + engines: {node: '>=8'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + ipaddr.js@2.2.0: + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} + engines: {node: '>= 10'} + + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + jose@5.10.0: + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + + js-xxhash@4.0.0: + resolution: {integrity: sha512-3Q2eIqG6s1KEBBmkj9tGM9lef8LJbuRyTVBdI3GpTnrvtytunjLPO0wqABp5qhtMzfA32jYn1FlnIV7GH1RAHQ==} + engines: {node: '>=18.0.0'} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-darwin-arm64@1.29.2: + resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.29.2: + resolution: {integrity: sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.29.2: + resolution: {integrity: sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.29.2: + resolution: {integrity: sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.29.2: + resolution: {integrity: sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.29.2: + resolution: {integrity: sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.29.2: + resolution: {integrity: sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.29.2: + resolution: {integrity: sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.29.2: + resolution: {integrity: sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.29.2: + resolution: {integrity: sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.29.2: + resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==} + engines: {node: '>= 12.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.castarray@4.4.0: + resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mini-svg-data-uri@1.4.4: + resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} + hasBin: true + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + motion-dom@12.5.0: + resolution: {integrity: sha512-uH2PETDh7m+Hjd1UQQ56yHqwn83SAwNjimNPE/kC+Kds0t4Yh7+29rfo5wezVFpPOv57U4IuWved5d1x0kNhbQ==} + + motion-utils@12.5.0: + resolution: {integrity: sha512-+hFFzvimn0sBMP9iPxBa9OtRX35ZQ3py0UHnb8U29VD+d8lQ8zH3dTygJWqK7av2v6yhg7scj9iZuvTS0f4+SA==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.1.2: + resolution: {integrity: sha512-b+CiXQCNMUGe0Ri64S9SXFcP9hogjAJ2Rd6GdVxhPLRm7mhGaM7VgOvCAJ1ZshfHbqVDI3uqTI5C8/GaKuLI7g==} + engines: {node: ^18 || >=20} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + next@15.2.2-canary.4: + resolution: {integrity: sha512-Apju+VEC86qN6gvM0JvsyCd46mEAlqupBz3apheFEoAjJBY+tsgFGLGFH+nqt/YJ2D1UEKh1g/HqqIqkQIDAog==} + engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.41.2 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-to-regexp@6.2.1: + resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + + postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + react-dom@19.0.0: + resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} + peerDependencies: + react: ^19.0.0 + + react@19.0.0: + resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} + engines: {node: '>=0.10.0'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + regexparam@1.3.0: + resolution: {integrity: sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g==} + engines: {node: '>=6'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + scheduler@0.25.0: + resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} + + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + + sonner@2.0.1: + resolution: {integrity: sha512-FRBphaehZ5tLdLcQ8g2WOIRE+Y7BCfWi5Zyd8bCvBjiW8TxxAyoWZIxS661Yz6TGPqFQ4VLzOF89WEYhfynSFQ==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + styled-jsx@5.1.6: + resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + + tailwindcss@4.0.15: + resolution: {integrity: sha512-6ZMg+hHdMJpjpeCCFasX7K+U615U9D+7k5/cDK/iRwl6GptF24+I/AbKgOnXhVKePzrEyIXutLv36n4cRsq3Sg==} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typescript@5.8.2: + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@alloc/quick-lru@5.2.0': {} + + '@edge-runtime/cookies@5.0.2': {} + + '@emnapi/runtime@1.3.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@eslint-community/eslint-utils@4.5.1(eslint@9.22.0(jiti@2.4.2))': + dependencies: + eslint: 9.22.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.19.2': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.1.0': {} + + '@eslint/core@0.12.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.0': + dependencies: + ajv: 6.12.6 + debug: 4.4.0 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.22.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.2.7': + dependencies: + '@eslint/core': 0.12.0 + levn: 0.4.1 + + '@floating-ui/core@1.6.9': + dependencies: + '@floating-ui/utils': 0.2.9 + + '@floating-ui/dom@1.6.13': + dependencies: + '@floating-ui/core': 1.6.9 + '@floating-ui/utils': 0.2.9 + + '@floating-ui/react-dom@2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@floating-ui/dom': 1.6.13 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + '@floating-ui/react@0.26.28(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@floating-ui/react-dom': 2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@floating-ui/utils': 0.2.9 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + tabbable: 6.2.0 + + '@floating-ui/utils@0.2.9': {} + + '@headlessui/react@2.2.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@floating-ui/react': 0.26.28(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@react-aria/focus': 3.20.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@react-aria/interactions': 3.24.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@tanstack/react-virtual': 3.13.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + '@heroicons/react@2.2.0(react@19.0.0)': + dependencies: + react: 19.0.0 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.2': {} + + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true + + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.3.1 + optional: true + + '@img/sharp-win32-ia32@0.33.5': + optional: true + + '@img/sharp-win32-x64@0.33.5': + optional: true + + '@next/env@15.2.2-canary.4': {} + + '@next/swc-darwin-arm64@15.2.2-canary.4': + optional: true + + '@next/swc-darwin-x64@15.2.2-canary.4': + optional: true + + '@next/swc-linux-arm64-gnu@15.2.2-canary.4': + optional: true + + '@next/swc-linux-arm64-musl@15.2.2-canary.4': + optional: true + + '@next/swc-linux-x64-gnu@15.2.2-canary.4': + optional: true + + '@next/swc-linux-x64-musl@15.2.2-canary.4': + optional: true + + '@next/swc-win32-arm64-msvc@15.2.2-canary.4': + optional: true + + '@next/swc-win32-x64-msvc@15.2.2-canary.4': + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@react-aria/focus@3.20.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@react-aria/interactions': 3.24.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@react-aria/utils': 3.28.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@react-types/shared': 3.28.0(react@19.0.0) + '@swc/helpers': 0.5.15 + clsx: 2.1.1 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + '@react-aria/interactions@3.24.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@react-aria/ssr': 3.9.7(react@19.0.0) + '@react-aria/utils': 3.28.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@react-stately/flags': 3.1.0 + '@react-types/shared': 3.28.0(react@19.0.0) + '@swc/helpers': 0.5.15 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + '@react-aria/ssr@3.9.7(react@19.0.0)': + dependencies: + '@swc/helpers': 0.5.15 + react: 19.0.0 + + '@react-aria/utils@3.28.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@react-aria/ssr': 3.9.7(react@19.0.0) + '@react-stately/flags': 3.1.0 + '@react-stately/utils': 3.10.5(react@19.0.0) + '@react-types/shared': 3.28.0(react@19.0.0) + '@swc/helpers': 0.5.15 + clsx: 2.1.1 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + '@react-stately/flags@3.1.0': + dependencies: + '@swc/helpers': 0.5.15 + + '@react-stately/utils@3.10.5(react@19.0.0)': + dependencies: + '@swc/helpers': 0.5.15 + react: 19.0.0 + + '@react-types/shared@3.28.0(react@19.0.0)': + dependencies: + react: 19.0.0 + + '@swc/counter@0.1.3': {} + + '@swc/helpers@0.5.15': + dependencies: + tslib: 2.8.1 + + '@tailwindcss/aspect-ratio@0.4.2(tailwindcss@4.0.15)': + dependencies: + tailwindcss: 4.0.15 + + '@tailwindcss/forms@0.5.10(tailwindcss@4.0.15)': + dependencies: + mini-svg-data-uri: 1.4.4 + tailwindcss: 4.0.15 + + '@tailwindcss/node@4.0.15': + dependencies: + enhanced-resolve: 5.18.1 + jiti: 2.4.2 + tailwindcss: 4.0.15 + + '@tailwindcss/oxide-android-arm64@4.0.15': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.0.15': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.0.15': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.0.15': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.15': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.0.15': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.0.15': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.0.15': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.0.15': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.0.15': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.0.15': + optional: true + + '@tailwindcss/oxide@4.0.15': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.0.15 + '@tailwindcss/oxide-darwin-arm64': 4.0.15 + '@tailwindcss/oxide-darwin-x64': 4.0.15 + '@tailwindcss/oxide-freebsd-x64': 4.0.15 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.15 + '@tailwindcss/oxide-linux-arm64-gnu': 4.0.15 + '@tailwindcss/oxide-linux-arm64-musl': 4.0.15 + '@tailwindcss/oxide-linux-x64-gnu': 4.0.15 + '@tailwindcss/oxide-linux-x64-musl': 4.0.15 + '@tailwindcss/oxide-win32-arm64-msvc': 4.0.15 + '@tailwindcss/oxide-win32-x64-msvc': 4.0.15 + + '@tailwindcss/postcss@4.0.15': + dependencies: + '@alloc/quick-lru': 5.2.0 + '@tailwindcss/node': 4.0.15 + '@tailwindcss/oxide': 4.0.15 + lightningcss: 1.29.2 + postcss: 8.5.3 + tailwindcss: 4.0.15 + + '@tailwindcss/typography@0.5.16(tailwindcss@4.0.15)': + dependencies: + lodash.castarray: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + postcss-selector-parser: 6.0.10 + tailwindcss: 4.0.15 + + '@tanstack/react-virtual@3.13.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@tanstack/virtual-core': 3.13.4 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + '@tanstack/virtual-core@3.13.4': {} + + '@tinyhttp/accepts@1.3.0': + dependencies: + es-mime-types: 0.0.16 + negotiator: 0.6.4 + + '@tinyhttp/app@1.3.0': + dependencies: + '@tinyhttp/cookie': 1.3.0 + '@tinyhttp/proxy-addr': 1.3.0 + '@tinyhttp/req': 1.3.0 + '@tinyhttp/res': 1.3.0 + '@tinyhttp/router': 1.3.0 + regexparam: 1.3.0 + + '@tinyhttp/content-disposition@1.3.0': {} + + '@tinyhttp/cookie-signature@1.3.0': {} + + '@tinyhttp/cookie@1.3.0': {} + + '@tinyhttp/encode-url@0.3.0': {} + + '@tinyhttp/etag@1.3.0': {} + + '@tinyhttp/forwarded@1.3.0': {} + + '@tinyhttp/proxy-addr@1.3.0': + dependencies: + '@tinyhttp/forwarded': 1.3.0 + ipaddr.js: 2.2.0 + + '@tinyhttp/req@1.3.0': + dependencies: + '@tinyhttp/accepts': 1.3.0 + '@tinyhttp/type-is': 1.3.0 + '@tinyhttp/url': 1.3.0 + es-fresh: 0.0.8 + range-parser: 1.2.1 + + '@tinyhttp/res@1.3.0': + dependencies: + '@tinyhttp/content-disposition': 1.3.0 + '@tinyhttp/cookie': 1.3.0 + '@tinyhttp/cookie-signature': 1.3.0 + '@tinyhttp/encode-url': 0.3.0 + '@tinyhttp/req': 1.3.0 + '@tinyhttp/send': 1.3.0 + es-mime-types: 0.0.16 + es-vary: 0.0.8 + escape-html: 1.0.3 + + '@tinyhttp/router@1.3.0': {} + + '@tinyhttp/send@1.3.0': + dependencies: + '@tinyhttp/etag': 1.3.0 + es-content-type: 0.0.10 + es-mime-types: 0.0.16 + + '@tinyhttp/type-is@1.3.0': + dependencies: + es-content-type: 0.0.10 + es-mime-types: 0.0.16 + + '@tinyhttp/url@1.3.0': {} + + '@types/estree@1.0.6': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@22.13.11': + dependencies: + undici-types: 6.20.0 + + '@types/react-dom@19.0.4(@types/react@19.0.12)': + dependencies: + '@types/react': 19.0.12 + + '@types/react@19.0.12': + dependencies: + csstype: 3.1.3 + + '@vercel/analytics@1.5.0(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)': + optionalDependencies: + next: 15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + + '@vercel/edge@1.2.1': {} + + '@vercel/microfrontends@1.0.0(@vercel/analytics@1.5.0(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0))(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + ajv: 8.17.1 + commander: 12.1.0 + cookie: 0.4.0 + fast-glob: 3.3.3 + http-proxy: 1.18.1 + jsonc-parser: 3.3.1 + path-to-regexp: 6.2.1 + optionalDependencies: + '@vercel/analytics': 1.5.0(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0) + next: 15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + transitivePeerDependencies: + - debug + + '@vercel/toolbar@0.1.33(@vercel/analytics@1.5.0(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0))(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@tinyhttp/app': 1.3.0 + '@vercel/microfrontends': 1.0.0(@vercel/analytics@1.5.0(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0))(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + chokidar: 3.6.0 + execa: 5.1.1 + fast-glob: 3.3.3 + find-up: 5.0.0 + get-port: 5.1.1 + jsonc-parser: 3.3.1 + strip-ansi: 6.0.1 + optionalDependencies: + next: 15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + transitivePeerDependencies: + - '@vercel/analytics' + - '@vercel/speed-insights' + - debug + - react-dom + + acorn-jsx@5.3.2(acorn@8.14.1): + dependencies: + acorn: 8.14.1 + + acorn@8.14.1: {} + + ajv@6.12.6: + 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 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + argparse@2.0.1: {} + + balanced-match@1.0.2: {} + + binary-extensions@2.3.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001706: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + client-only@0.0.1: {} + + clsx@2.1.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + optional: true + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + optional: true + + commander@12.1.0: {} + + concat-map@0.0.1: {} + + cookie@0.4.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssesc@3.0.0: {} + + csstype@3.1.3: {} + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + detect-libc@2.0.3: {} + + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + es-content-type@0.0.10: {} + + es-fresh@0.0.8: {} + + es-mime-types@0.0.16: + dependencies: + mime-db: 1.54.0 + + es-vary@0.0.8: {} + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: {} + + eslint-scope@8.3.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint@9.22.0(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.5.1(eslint@9.22.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.19.2 + '@eslint/config-helpers': 0.1.0 + '@eslint/core': 0.12.0 + '@eslint/eslintrc': 3.3.0 + '@eslint/js': 9.22.0 + '@eslint/plugin-kit': 0.2.7 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.2 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0 + escape-string-regexp: 4.0.0 + eslint-scope: 8.3.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + + espree@10.3.0: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint-visitor-keys: 4.2.0 + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + eventemitter3@4.0.7: {} + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + 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.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.0.6: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flags@4.0.0(next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + '@edge-runtime/cookies': 5.0.2 + jose: 5.10.0 + optionalDependencies: + next: 15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + flagsmith@9.2.2: {} + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + follow-redirects@1.15.9: {} + + framer-motion@12.4.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + motion-dom: 12.5.0 + motion-utils: 12.5.0 + tslib: 2.8.1 + optionalDependencies: + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + fsevents@2.3.3: + optional: true + + get-port@5.1.1: {} + + get-stream@6.0.1: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@14.0.0: {} + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.9 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + + human-signals@2.1.0: {} + + ignore@5.3.2: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + ipaddr.js@2.2.0: {} + + is-arrayish@0.3.2: + optional: true + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-stream@2.0.1: {} + + isexe@2.0.0: {} + + jiti@2.4.2: {} + + jose@5.10.0: {} + + js-xxhash@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + jsonc-parser@3.3.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-darwin-arm64@1.29.2: + optional: true + + lightningcss-darwin-x64@1.29.2: + optional: true + + lightningcss-freebsd-x64@1.29.2: + optional: true + + lightningcss-linux-arm-gnueabihf@1.29.2: + optional: true + + lightningcss-linux-arm64-gnu@1.29.2: + optional: true + + lightningcss-linux-arm64-musl@1.29.2: + optional: true + + lightningcss-linux-x64-gnu@1.29.2: + optional: true + + lightningcss-linux-x64-musl@1.29.2: + optional: true + + lightningcss-win32-arm64-msvc@1.29.2: + optional: true + + lightningcss-win32-x64-msvc@1.29.2: + optional: true + + lightningcss@1.29.2: + dependencies: + detect-libc: 2.0.3 + optionalDependencies: + lightningcss-darwin-arm64: 1.29.2 + lightningcss-darwin-x64: 1.29.2 + lightningcss-freebsd-x64: 1.29.2 + lightningcss-linux-arm-gnueabihf: 1.29.2 + lightningcss-linux-arm64-gnu: 1.29.2 + lightningcss-linux-arm64-musl: 1.29.2 + lightningcss-linux-x64-gnu: 1.29.2 + lightningcss-linux-x64-musl: 1.29.2 + lightningcss-win32-arm64-msvc: 1.29.2 + lightningcss-win32-x64-msvc: 1.29.2 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.castarray@4.4.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.merge@4.6.2: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.54.0: {} + + mimic-fn@2.1.0: {} + + mini-svg-data-uri@1.4.4: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + motion-dom@12.5.0: + dependencies: + motion-utils: 12.5.0 + + motion-utils@12.5.0: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + nanoid@5.1.2: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.4: {} + + next@15.2.2-canary.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + '@next/env': 15.2.2-canary.4 + '@swc/counter': 0.1.3 + '@swc/helpers': 0.5.15 + busboy: 1.6.0 + caniuse-lite: 1.0.30001706 + postcss: 8.4.31 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + styled-jsx: 5.1.6(react@19.0.0) + optionalDependencies: + '@next/swc-darwin-arm64': 15.2.2-canary.4 + '@next/swc-darwin-x64': 15.2.2-canary.4 + '@next/swc-linux-arm64-gnu': 15.2.2-canary.4 + '@next/swc-linux-arm64-musl': 15.2.2-canary.4 + '@next/swc-linux-x64-gnu': 15.2.2-canary.4 + '@next/swc-linux-x64-musl': 15.2.2-canary.4 + '@next/swc-win32-arm64-msvc': 15.2.2-canary.4 + '@next/swc-win32-x64-msvc': 15.2.2-canary.4 + sharp: 0.33.5 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + normalize-path@3.0.0: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + optionator@0.9.4: + 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 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-to-regexp@6.2.1: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + postcss-selector-parser@6.0.10: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss@8.4.31: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + postcss@8.5.3: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} + + range-parser@1.2.1: {} + + react-dom@19.0.0(react@19.0.0): + dependencies: + react: 19.0.0 + scheduler: 0.25.0 + + react@19.0.0: {} + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + regexparam@1.3.0: {} + + require-from-string@2.0.2: {} + + requires-port@1.0.0: {} + + resolve-from@4.0.0: {} + + reusify@1.1.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + scheduler@0.25.0: {} + + semver@7.7.1: + optional: true + + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.7.1 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + optional: true + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@3.0.7: {} + + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + optional: true + + sonner@2.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + source-map-js@1.2.1: {} + + streamsearch@1.1.0: {} + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-final-newline@2.0.0: {} + + strip-json-comments@3.1.1: {} + + styled-jsx@5.1.6(react@19.0.0): + dependencies: + client-only: 0.0.1 + react: 19.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + tabbable@6.2.0: {} + + tailwindcss@4.0.15: {} + + tapable@2.2.1: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tslib@2.8.1: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typescript@5.8.2: {} + + undici-types@6.20.0: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + yocto-queue@0.1.0: {} diff --git a/flags-sdk/flagsmith/postcss.config.mjs b/flags-sdk/flagsmith/postcss.config.mjs new file mode 100644 index 000000000..5d6d8457f --- /dev/null +++ b/flags-sdk/flagsmith/postcss.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + '@tailwindcss/postcss': {}, + }, +}; + +export default config; diff --git a/flags-sdk/flagsmith/public/images/pool.jpg b/flags-sdk/flagsmith/public/images/pool.jpg new file mode 100644 index 000000000..3759829b5 Binary files /dev/null and b/flags-sdk/flagsmith/public/images/pool.jpg differ diff --git a/flags-sdk/flagsmith/public/images/product/shirt-black.avif b/flags-sdk/flagsmith/public/images/product/shirt-black.avif new file mode 100644 index 000000000..3ca437e26 Binary files /dev/null and b/flags-sdk/flagsmith/public/images/product/shirt-black.avif differ diff --git a/flags-sdk/flagsmith/public/images/product/shirt-blue.avif b/flags-sdk/flagsmith/public/images/product/shirt-blue.avif new file mode 100644 index 000000000..1888ea9b8 Binary files /dev/null and b/flags-sdk/flagsmith/public/images/product/shirt-blue.avif differ diff --git a/flags-sdk/flagsmith/public/images/product/shirt-white.avif b/flags-sdk/flagsmith/public/images/product/shirt-white.avif new file mode 100644 index 000000000..3a2895ea1 Binary files /dev/null and b/flags-sdk/flagsmith/public/images/product/shirt-white.avif differ diff --git a/flags-sdk/flagsmith/tailwind.config.ts b/flags-sdk/flagsmith/tailwind.config.ts new file mode 100644 index 000000000..18ecd09b4 --- /dev/null +++ b/flags-sdk/flagsmith/tailwind.config.ts @@ -0,0 +1,15 @@ +import type { Config } from 'tailwindcss' + +const config: Config = { + content: [ + './components/**/*.{js,ts,jsx,tsx,mdx}', + './app/**/*.{js,ts,jsx,tsx,mdx}', + ], + plugins: [ + require('@tailwindcss/forms'), + require('@tailwindcss/typography'), + require('@tailwindcss/aspect-ratio'), + ], +} + +export default config diff --git a/flags-sdk/flagsmith/tsconfig.json b/flags-sdk/flagsmith/tsconfig.json new file mode 100644 index 000000000..64c21044c --- /dev/null +++ b/flags-sdk/flagsmith/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + }, + "target": "ES2017" + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +}