From 5e1284241b86793df732dbdee85cfc55616121dd Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sat, 6 Jun 2026 16:56:00 -0500 Subject: [PATCH 01/13] [template] media: remove gray background behind PDP grid and product card images (#317) Drop bg-accent from the PDP desktop grid tiles and bg-muted from the product card image container so product imagery sits flush on the page background. The PDP mobile carousel already had no backing, so the two viewports now match. The product card's no-image fallback keeps its gray box (bg-muted moved onto the fallback div). Co-authored-by: Claude Opus 4.7 --- .../components/product-card/components.tsx | 4 +- .../product-detail/product-media.tsx | 2 +- .../2026-06-06-remove-media-backgrounds.md | 41 +++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 packages/plugin/template-rollout-log/2026-06-06-remove-media-backgrounds.md diff --git a/apps/template/components/product-card/components.tsx b/apps/template/components/product-card/components.tsx index 8aaa2315..82516b35 100644 --- a/apps/template/components/product-card/components.tsx +++ b/apps/template/components/product-card/components.tsx @@ -86,12 +86,12 @@ function ProductCardImage({
{src ? ( {alt} ) : ( -
+
{fallbackTitle}
)} diff --git a/apps/template/components/product-detail/product-media.tsx b/apps/template/components/product-detail/product-media.tsx index 036701f1..4843f456 100644 --- a/apps/template/components/product-detail/product-media.tsx +++ b/apps/template/components/product-detail/product-media.tsx @@ -210,7 +210,7 @@ function GridItem({ eager: boolean; }) { return ( -
+
{item.type === "video" ? ( ` so a product without a `featuredImage` still renders as a gray box with its centered title — only cards that actually have an image lose the backing color. + +## Why it matters + +- `object-cover` images fully fill the square, so the backing color was only ever visible behind transparent PNGs or during the brief image fetch. On a white page it read as a faint gray frame rather than an intentional surface. +- Removing it lets product imagery sit directly on the page background and keeps the PDP grid and carousel visually consistent. + +## Apply when + +- The storefront uses the template's `ProductCard` and PDP `ProductMedia` largely as shipped and wants imagery flush on the page background. + +## Safe to skip when + +- The storefront deliberately wants a gray frame behind product imagery (e.g. for predominantly transparent-PNG catalogs where the backing color provides contrast during load). +- `ProductCardImage` / `GridItem` have been customized with their own background. + +## Validation + +1. `pnpm --filter template dev`. +2. Load a PDP on desktop (`lg`) and confirm grid tiles have no gray backing behind images; load on mobile and confirm the carousel is unchanged. +3. Load a collection/search grid and confirm product cards with images have no gray backing. +4. Render a product with no `featuredImage` and confirm the fallback still shows a gray (`bg-muted`) box with the title. +5. `pnpm --filter template lint` and `pnpm --filter template exec tsc --noEmit` clean. From 42dbfe817139bfd404c47c021ae182615ed66cb7 Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 07:12:06 -0500 Subject: [PATCH 02/13] fix: lint warnings and format issues across template + docs (#318) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: lint warnings and format issues across template + docs - Run oxfmt on previously-unformatted files in apps/template and 2 mdx files in apps/docs (caught by oxfmt --check). - Add `no-underscore-dangle` allow lists to both .oxlintrc.json files for names we don't control: __typename (Shopify GraphQL), __dirname (Node builtin), __registerFileInput (vendored AI Elements). - Fix react-hooks/exhaustive-deps warnings in template-owned code: - agent-panel.tsx: include onOpenChange and triggerRef in the outside-click effect's deps. - use-scroll-contain.ts: include ref in deps (refs are stable; replaces a no-longer-effective oxlint-disable comment). - cart/context.tsx: add oxlint-disable comments on the unmount cleanup that intentionally reads ref.current at teardown. The only remaining warnings are in vendored components/ai-elements code, left alone by design. Co-Authored-By: Claude Opus 4.7 (1M context) * chore: expand alphabetization rule, apply to shopify operations (#319) * chore: expand alphabetization rule and apply it across shopify operations The Ordering rule in apps/template/AGENTS.md previously named only four things to alphabetize: export specifiers, i18n JSON keys, string union type members, and config object keys. That left object destructuring patterns and interface/type properties undefined — and `operations/` had drifted accordingly. Update the rule wording to include both, then bring `operations/products.ts` and `operations/cart.ts` into compliance: - products.ts: alphabetize all parameter types, destructuring patterns, and return-shape literals across `buildCatalogQuery`, `fetchCatalogProducts`, `getSearchFacets`, `searchIndexProducts`, and `getCollectionProducts`. - cart.ts: alphabetize the `addCartDeliveryAddress`/`updateCartDeliveryAddress` address parameter types and the `CartShippingOption` type (and the matching GraphQL response shape + the `.map()` literal that builds it). Out of scope: GraphQL `variables: { ... }` payloads (they mirror query variable order) and lib/types.ts type declarations (a separate sweep). Co-Authored-By: Claude Opus 4.7 (1M context) * chore: alphabetize properties in lib/types.ts Brings the domain-type contract module in line with the alphabetization rule. Pure interface property reordering (plus FilterType string union) — no runtime effect; TypeScript doesn't require literal field order to match type declaration order, so consumers are unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) --------- Co-authored-by: Claude Opus 4.7 (1M context) --------- Co-authored-by: Claude Opus 4.7 (1M context) --- apps/docs/.oxlintrc.json | 1 + apps/docs/content/docs/anatomy/webhooks.mdx | 16 +- .../getting-started/extending-with-agents.mdx | 8 +- apps/template/.oxlintrc.json | 1 + apps/template/AGENTS.md | 2 +- apps/template/app/api/chat/route.ts | 1 + apps/template/app/cart/page.tsx | 5 +- .../template/components/agent/agent-panel.tsx | 2 +- apps/template/components/cart/context.tsx | 2 + apps/template/components/search/results.tsx | 7 +- apps/template/hooks/use-scroll-contain.ts | 3 +- apps/template/lib/cart/action.ts | 4 +- apps/template/lib/shopify/operations/cart.ts | 31 ++-- .../lib/shopify/operations/products.ts | 62 ++++---- apps/template/lib/types.ts | 140 +++++++++--------- 15 files changed, 137 insertions(+), 148 deletions(-) diff --git a/apps/docs/.oxlintrc.json b/apps/docs/.oxlintrc.json index 772d3749..9cfc4975 100644 --- a/apps/docs/.oxlintrc.json +++ b/apps/docs/.oxlintrc.json @@ -7,6 +7,7 @@ "ignorePatterns": [".next/**", "dist/**", "build/**", ".claude/**"], "plugins": ["typescript", "react", "nextjs"], "rules": { + "no-underscore-dangle": ["warn", { "allow": ["__dirname", "__registerFileInput"] }], "no-unused-vars": "off", "react/react-in-jsx-scope": "off" }, diff --git a/apps/docs/content/docs/anatomy/webhooks.mdx b/apps/docs/content/docs/anatomy/webhooks.mdx index ba0ab9ea..cdf1855d 100644 --- a/apps/docs/content/docs/anatomy/webhooks.mdx +++ b/apps/docs/content/docs/anatomy/webhooks.mdx @@ -35,11 +35,11 @@ Product topics also try to derive a numeric product tag from `admin_graphql_api_ Metaobject topics inspect the payload's `type` field to invalidate narrower CMS tags. The exact mapping follows the conventions used by [Shopify CMS](/docs/skills/enable-shopify-cms): -| Metaobject `type` | Additional tags | -| ---------------------------- | -------------------------------- | -| `cms_page` | `cms:pages`, `cms:page:{slug}` | -| `cms_homepage` | `cms:homepage` | -| `cms_section`, `cms_hero` | `cms:pages`, `cms:homepage` | +| Metaobject `type` | Additional tags | +| ------------------------- | ------------------------------ | +| `cms_page` | `cms:pages`, `cms:page:{slug}` | +| `cms_homepage` | `cms:homepage` | +| `cms_section`, `cms_hero` | `cms:pages`, `cms:homepage` | All metaobject topics also invalidate the broad `cms:all` tag as a safety net for unrecognized types. @@ -70,9 +70,9 @@ You can register only the topics you care about. Skipping `inventory_levels/*`, ## Environment variables -| Variable | When to set | -| ------------------------- | ---------------------------------------------------------------------------------- | -| `SHOPIFY_WEBHOOK_SECRET` | Required in any environment where Shopify posts to `/api/webhooks/shopify`. Without it, signature verification is skipped — fine for local testing, unsafe for production. | +| Variable | When to set | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `SHOPIFY_WEBHOOK_SECRET` | Required in any environment where Shopify posts to `/api/webhooks/shopify`. Without it, signature verification is skipped — fine for local testing, unsafe for production. | See [Environment Variables](/docs/reference/env-vars) for the full reference. diff --git a/apps/docs/content/docs/getting-started/extending-with-agents.mdx b/apps/docs/content/docs/getting-started/extending-with-agents.mdx index 58f0e55a..4fe4dc9b 100644 --- a/apps/docs/content/docs/getting-started/extending-with-agents.mdx +++ b/apps/docs/content/docs/getting-started/extending-with-agents.mdx @@ -57,10 +57,10 @@ The owning tool can overwrite the content between `BEGIN` and `END` on upgrade w The template ships with two blocks: -| Block | Owner | What it contains | -| -------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `nextjs-agent-rules` | Next.js | Reminds agents this Next.js version has breaking changes and to read bundled docs before writing code. Refreshed on Next.js upgrade. | -| `vercel-shop-style` | Vercel Shop | Code style conventions: alphabetized exports and keys, no barrel files, push `"use client"` to leaves, naming rules, Tailwind patterns. Remove the block if your team prefers different conventions. | +| Block | Owner | What it contains | +| -------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `nextjs-agent-rules` | Next.js | Reminds agents this Next.js version has breaking changes and to read bundled docs before writing code. Refreshed on Next.js upgrade. | +| `vercel-shop-style` | Vercel Shop | Code style conventions: alphabetized exports and keys, no barrel files, push `"use client"` to leaves, naming rules, Tailwind patterns. Remove the block if your team prefers different conventions. | Everything outside these markers is yours. Add team conventions or domain constraints anywhere else and no upgrade will overwrite them. diff --git a/apps/template/.oxlintrc.json b/apps/template/.oxlintrc.json index 8f67a4b1..d36a0e6a 100644 --- a/apps/template/.oxlintrc.json +++ b/apps/template/.oxlintrc.json @@ -7,6 +7,7 @@ "ignorePatterns": [".next/**", "dist/**", "build/**", ".claude/**", "app/.well-known/**"], "plugins": ["typescript", "react", "nextjs"], "rules": { + "no-underscore-dangle": ["warn", { "allow": ["__typename"] }], "no-unused-vars": "off", "react/react-in-jsx-scope": "off" }, diff --git a/apps/template/AGENTS.md b/apps/template/AGENTS.md index 677428c2..cfd7e00d 100644 --- a/apps/template/AGENTS.md +++ b/apps/template/AGENTS.md @@ -38,7 +38,7 @@ This version has breaking changes — APIs, conventions, and file structure may ### Ordering & Organization -- Alphabetize named export specifiers, i18n JSON keys (within each section and at the top level), string union type members, and config object keys. +- Alphabetize named export specifiers, object destructuring patterns, interface and type properties, config object keys, i18n JSON keys (within each section and at the top level), and string union type members. - No barrel files — never create an `index.ts` that only re-exports. Import from the source file directly. - oxfmt handles import sorting automatically via `pnpm format`. diff --git a/apps/template/app/api/chat/route.ts b/apps/template/app/api/chat/route.ts index 2cfc7b40..62b67b90 100644 --- a/apps/template/app/api/chat/route.ts +++ b/apps/template/app/api/chat/route.ts @@ -5,6 +5,7 @@ import { createUIMessageStreamResponse, safeValidateUIMessages, } from "ai"; + import { createAgent, type PageContext, type User, withAgentContext } from "@/lib/agent/server"; import { buildCartIdSetCookieHeader, getCartIdFromCookie } from "@/lib/cart/server"; import { agent as agentConfig } from "@/lib/config"; diff --git a/apps/template/app/cart/page.tsx b/apps/template/app/cart/page.tsx index 3cb46c9b..d05ee25f 100644 --- a/apps/template/app/cart/page.tsx +++ b/apps/template/app/cart/page.tsx @@ -43,10 +43,7 @@ export default async function CartPage() { } async function CartContent({ locale }: { locale: Locale }) { - const [cart, messages] = await Promise.all([ - withFallback(getCart(), undefined), - getMessages(), - ]); + const [cart, messages] = await Promise.all([withFallback(getCart(), undefined), getMessages()]); return ( diff --git a/apps/template/components/agent/agent-panel.tsx b/apps/template/components/agent/agent-panel.tsx index 262dabdc..0474dce6 100644 --- a/apps/template/components/agent/agent-panel.tsx +++ b/apps/template/components/agent/agent-panel.tsx @@ -398,7 +398,7 @@ export function AgentPanel({ open, onOpenChange, triggerRef }: AgentPanelProps) document.removeEventListener("mousedown", handleClickOutside); document.removeEventListener("keydown", handleEscape); }; - }, [open]); + }, [open, onOpenChange, triggerRef]); useScrollContain(panelRef, open); diff --git a/apps/template/components/cart/context.tsx b/apps/template/components/cart/context.tsx index 1036a0ff..638dc47a 100644 --- a/apps/template/components/cart/context.tsx +++ b/apps/template/components/cart/context.tsx @@ -484,11 +484,13 @@ export function CartProvider({ clearTimeout(debounce.timer); } + // oxlint-disable-next-line react-hooks/exhaustive-deps -- clear timers held at unmount, not at effect setup for (const [, pending] of lineOpsRef.current) { if (pending.timer !== null) { clearTimeout(pending.timer); } } + // oxlint-disable-next-line react-hooks/exhaustive-deps -- clear the latest request-id map at unmount latestLineRequestIdRef.current.clear(); }; }, []); diff --git a/apps/template/components/search/results.tsx b/apps/template/components/search/results.tsx index 703caab0..e52e5ab2 100644 --- a/apps/template/components/search/results.tsx +++ b/apps/template/components/search/results.tsx @@ -16,12 +16,7 @@ import { searchIndexProducts, } from "@/lib/shopify/operations/products"; import type { ProductFilter } from "@/lib/shopify/types/filters"; -import type { - Filter, - PageInfo, - PriceRange, - ProductCard as ProductCardType, -} from "@/lib/types"; +import type { Filter, PageInfo, PriceRange, ProductCard as ProductCardType } from "@/lib/types"; import { RESULTS_PER_PAGE } from "@/lib/utils"; export interface SearchResultsData { diff --git a/apps/template/hooks/use-scroll-contain.ts b/apps/template/hooks/use-scroll-contain.ts index 86d86431..8a4d640b 100644 --- a/apps/template/hooks/use-scroll-contain.ts +++ b/apps/template/hooks/use-scroll-contain.ts @@ -46,7 +46,6 @@ export function useScrollContain( e.preventDefault(); }); - // oxlint-disable-next-line react/exhaustive-deps -- ref is stable; enabled changing to true coincides with the panel mounting useEffect(() => { if (!enabled) return; const panel = ref.current; @@ -61,5 +60,5 @@ export function useScrollContain( panel.removeEventListener("touchstart", onTouchStart); panel.removeEventListener("touchmove", onTouchMove); }; - }, [enabled]); + }, [enabled, ref]); } diff --git a/apps/template/lib/cart/action.ts b/apps/template/lib/cart/action.ts index 9490eb9f..51f706d8 100644 --- a/apps/template/lib/cart/action.ts +++ b/apps/template/lib/cart/action.ts @@ -231,9 +231,7 @@ export async function applyDiscountCodeAction(code: string): Promise d.code.toUpperCase() === normalized, - ); + const applied = result.cart.discountCodes.find((d) => d.code.toUpperCase() === normalized); if (applied && !applied.applicable) { const reverted = await updateCartDiscountCodes(existing); const errorMessage = diff --git a/apps/template/lib/shopify/operations/cart.ts b/apps/template/lib/shopify/operations/cart.ts index 954bde09..715e4a95 100644 --- a/apps/template/lib/shopify/operations/cart.ts +++ b/apps/template/lib/shopify/operations/cart.ts @@ -1,8 +1,4 @@ -import { - getCartIdFromCookie, - invalidateCartCache, - setCartIdCookie, -} from "@/lib/cart/server"; +import { getCartIdFromCookie, invalidateCartCache, setCartIdCookie } from "@/lib/cart/server"; import { defaultLocale, getCountryCode, getLanguageCode } from "@/lib/i18n"; import type { Cart, CartWarning } from "@/lib/types"; @@ -203,7 +199,10 @@ const CART_DELIVERY_ADDRESSES_UPDATE_MUTATION = ` export type CartMutationResult = { cart: Cart; warnings: CartWarning[] }; -function applyMutation(payload: CartMutationPayload, operation: string): CartMutationResult { +function applyMutation( + payload: CartMutationPayload, + operation: string, +): CartMutationResult { const { cart, warnings } = unwrapCartMutation(payload, operation); return { cart: transformShopifyCart(cart), warnings }; } @@ -229,7 +228,9 @@ export async function getCart(cartId?: string): Promise { * Use in streaming contexts (e.g., the AI agent) where `cookies().set()` won't work. * The caller is responsible for setting the cookie via response headers. */ -export async function createCartWithoutCookie(locale: string = defaultLocale): Promise { +export async function createCartWithoutCookie( + locale: string = defaultLocale, +): Promise { const country = getCountryCode(locale); const language = getLanguageCode(locale); @@ -445,8 +446,8 @@ export async function getCartSelectableAddressId(): Promise export async function addCartDeliveryAddress(address: { city?: string; countryCode: string; - zip?: string; customerAddressId?: string; + zip?: string; }): Promise { const cartId = await getCartIdFromCookie(); if (!cartId) return undefined; @@ -485,9 +486,9 @@ export async function addCartDeliveryAddress(address: { } export type CartShippingOption = { - title: string; - estimatedCost: { amount: string; currencyCode: string }; deliveryMethodType: string; + estimatedCost: { amount: string; currencyCode: string }; + title: string; }; export async function getCartDeliveryOptions(): Promise { @@ -499,9 +500,9 @@ export async function getCartDeliveryOptions(): Promise { deliveryGroups: { nodes: Array<{ deliveryOptions: Array<{ - title: string | null; - estimatedCost: { amount: string; currencyCode: string }; deliveryMethodType: string; + estimatedCost: { amount: string; currencyCode: string }; + title: string | null; }>; }>; }; @@ -524,9 +525,9 @@ export async function getCartDeliveryOptions(): Promise { return true; }) .map((opt) => ({ - title: opt.title ?? opt.deliveryMethodType, - estimatedCost: opt.estimatedCost, deliveryMethodType: opt.deliveryMethodType, + estimatedCost: opt.estimatedCost, + title: opt.title ?? opt.deliveryMethodType, })); } @@ -535,8 +536,8 @@ export async function updateCartDeliveryAddress( address: { city?: string; countryCode: string; - zip?: string; customerAddressId?: string; + zip?: string; }, ): Promise { const cartId = await getCartIdFromCookie(); diff --git a/apps/template/lib/shopify/operations/products.ts b/apps/template/lib/shopify/operations/products.ts index 8e5b5616..b4ec4c2b 100644 --- a/apps/template/lib/shopify/operations/products.ts +++ b/apps/template/lib/shopify/operations/products.ts @@ -192,9 +192,9 @@ function joinOr(field: string, values: string[]): string { // QueryRoot.products has no productFilters arg, so filters are encoded into the query string; variantOption/productMetafield are dropped. function buildCatalogQuery(args: { - query?: string; collection?: string; filters: ProductFilter[]; + query?: string; }): string { const parts: string[] = []; @@ -321,8 +321,8 @@ export function buildProductFiltersFromParams( } type CatalogProductsResult = { - products: ProductCard[]; pageInfo: PageInfo; + products: ProductCard[]; }; type CatalogProductsParams = { @@ -331,21 +331,21 @@ type CatalogProductsParams = { }; type FilteredCatalogProductsParams = CatalogProductsParams & { - query?: string; collection?: string; - sortKey?: string; cursor?: string; filters?: ProductFilter[]; + query?: string; + sortKey?: string; }; async function fetchCatalogProducts({ - query, collection, - sortKey: rawSortKey = "best-matches", - limit = 50, cursor, filters = [], + limit = 50, locale = defaultLocale, + query, + sortKey: rawSortKey = "best-matches", }: FilteredCatalogProductsParams): Promise { const sortConfig = CATALOG_SORT_KEY_MAP[rawSortKey] ?? CATALOG_SORT_KEY_MAP["best-matches"]; const country = getCountryCode(locale); @@ -382,8 +382,8 @@ async function fetchCatalogProducts({ tagProducts(shopifyProducts); return { - products: shopifyProducts.map(transformShopifyProductCard), pageInfo: data.products.pageInfo, + products: shopifyProducts.map(transformShopifyProductCard), }; } @@ -409,22 +409,16 @@ export async function getFilteredCatalogProducts( export async function getSearchFacets(params: { activeFilters?: ActiveFilters; - query?: string; collection?: string; filters?: ProductFilter[]; locale?: string; + query?: string; }): Promise<{ filters: Filter[]; priceRange?: PriceRange; total: number }> { "use cache: remote"; cacheLife("max"); cacheTag("products"); - const { - activeFilters = {}, - query, - collection, - filters = [], - locale = defaultLocale, - } = params; + const { activeFilters = {}, collection, filters = [], locale = defaultLocale, query } = params; const country = getCountryCode(locale); const language = getLanguageCode(locale); @@ -462,26 +456,26 @@ export async function getSearchFacets(params: { // (variant options, metafields, etc.) — the products(...) query string in getCatalogProducts // silently drops variantOption/productMetafield, so /search uses this path even for no-query browse. export async function searchIndexProducts(params: { - query?: string; collection?: string; - sortKey?: string; - limit?: number; cursor?: string; filters?: ProductFilter[]; + limit?: number; locale?: string; -}): Promise<{ products: ProductCard[]; total: number; pageInfo: PageInfo }> { + query?: string; + sortKey?: string; +}): Promise<{ pageInfo: PageInfo; products: ProductCard[]; total: number }> { "use cache: remote"; cacheLife("max"); cacheTag("products"); const { - query, collection, - sortKey: rawSortKey = "best-matches", - limit = 50, cursor, filters = [], + limit = 50, locale = defaultLocale, + query, + sortKey: rawSortKey = "best-matches", } = params; const sortConfig = SEARCH_SORT_KEY_MAP[rawSortKey] ?? SEARCH_SORT_KEY_MAP["best-matches"]; @@ -522,9 +516,9 @@ export async function searchIndexProducts(params: { tagProducts(shopifyProducts); return { + pageInfo: data.search.pageInfo, products: shopifyProducts.map(transformShopifyProductCard), total: data.search.totalCount, - pageInfo: data.search.pageInfo, }; } @@ -582,16 +576,16 @@ const COLLECTION_SORT_KEY_MAP: Record { "use cache: remote"; cacheLife("max"); @@ -600,11 +594,11 @@ export async function getCollectionProducts(params: { const { activeFilters = {}, collection, - sortKey: rawSortKey = "best-matches", - limit = 50, cursor, filters = [], + limit = 50, locale = defaultLocale, + sortKey: rawSortKey = "best-matches", } = params; const sortConfig = COLLECTION_SORT_KEY_MAP[rawSortKey] ?? COLLECTION_SORT_KEY_MAP["best-matches"]; @@ -636,14 +630,14 @@ export async function getCollectionProducts(params: { if (!data.collection) { return { - products: [], + filters: [], pageInfo: { hasNextPage: false, hasPreviousPage: false, startCursor: null, endCursor: null, }, - filters: [], + products: [], }; } @@ -655,10 +649,10 @@ export async function getCollectionProducts(params: { const transformed = transformShopifyFilters(data.collection.products.filters, { activeFilters }); return { - products, - pageInfo: data.collection.products.pageInfo, filters: transformed.filters, + pageInfo: data.collection.products.pageInfo, priceRange: transformed.priceRange, + products, }; } diff --git a/apps/template/lib/types.ts b/apps/template/lib/types.ts index 06ee79f2..330aa8a0 100644 --- a/apps/template/lib/types.ts +++ b/apps/template/lib/types.ts @@ -23,68 +23,68 @@ export interface Money { } export interface Image { - url: string; altText: string; - width: number; height: number; + url: string; + width: number; } export interface Video { - url: string; + height: number; previewImage: Image | null; + url: string; width: number; - height: number; } export interface SEO { - title: string; description: string; + title: string; } export interface ProductCard { - id: string; - handle: string; - title: string; - featuredImage: Image | null; - price: Money; - compareAtPrice?: Money; - vendor?: string; availableForSale: boolean; + compareAtPrice?: Money; defaultVariantId?: string; defaultVariantNumericId?: string; defaultVariantSelectedOptions?: SelectedOption[]; + featuredImage: Image | null; + handle: string; + id: string; + price: Money; + title: string; + vendor?: string; } export interface ProductDetails extends ProductCard { + category?: Category | null; + categoryId?: string; + collectionHandles: string[]; + currencyCode: string; description: string; descriptionHtml: string; images: Image[]; - videos: Video[]; - variants: ProductVariant[]; + manufacturerName: string; + metafields?: Metafield[]; options: ProductOption[]; - tags: string[]; - seo: SEO; - category?: Category | null; - updatedAt: string; priceRange: { - minVariantPrice: Money; maxVariantPrice: Money; + minVariantPrice: Money; }; - currencyCode: string; - manufacturerName: string; - categoryId?: string; - collectionHandles: string[]; - metafields?: Metafield[]; + seo: SEO; + tags: string[]; + updatedAt: string; + variants: ProductVariant[]; + videos: Video[]; } export interface ProductVariant { - id: string; - title: string; availableForSale: boolean; - price: Money; compareAtPrice?: Money; - selectedOptions: SelectedOption[]; + id: string; image: Image | null; + price: Money; + selectedOptions: SelectedOption[]; + title: string; } export interface ProductOption { @@ -116,41 +116,41 @@ export interface Metafield { } export interface Category { + ancestors: Category[]; id: string; name: string; - ancestors: Category[]; } export interface Cart { - id: string | undefined; + appliedGiftCards: AppliedGiftCard[]; checkoutUrl: string; - totalQuantity: number; - note: string | null; cost: { subtotalAmount: Money; totalAmount: Money; totalTaxAmount: Money; }; + discountAllocations: DiscountAllocation[]; + discountCodes: DiscountCode[]; + id: string | undefined; lines: CartLine[]; + note: string | null; shippingCost: Money | null; - discountCodes: DiscountCode[]; - discountAllocations: DiscountAllocation[]; - appliedGiftCards: AppliedGiftCard[]; + totalQuantity: number; } export interface CartLine { - id: string | undefined; - quantity: number; cost: { totalAmount: Money; }; - merchandise: CartMerchandise; discountAllocations: DiscountAllocation[]; + id: string | undefined; + merchandise: CartMerchandise; + quantity: number; } export interface DiscountCode { - code: string; applicable: boolean; + code: string; } export type DiscountAllocation = @@ -172,90 +172,90 @@ export interface CartWarning { export interface CartMerchandise { id: string; - title: string; image?: Image; price?: Money; - selectedOptions: SelectedOption[]; product: CartProduct; + selectedOptions: SelectedOption[]; + title: string; } export interface CartProduct { - id: string; + featuredImage: Image; handle: string; + id: string; title: string; - featuredImage: Image; } export interface Collection { - handle: string; - title: string; description: string; + handle: string; image?: Image | null; - seo: SEO; path: string; + seo: SEO; + title: string; updatedAt: string; } -export type FilterType = "list" | "price" | "boolean"; +export type FilterType = "boolean" | "list" | "price"; export interface FilterValue { + count: number; id: string; label: string; value: string; - count: number; } export interface Filter { id: string; label: string; - type: FilterType; paramKey: string; + type: FilterType; values: FilterValue[]; } export interface PriceRange { - min: number; max: number; + min: number; } export interface CategoryNavItem { + count: number; + href: string; id: string; label: string; slug: string; - count: number; - href: string; } export interface PageInfo { + endCursor: string | null; hasNextPage: boolean; hasPreviousPage: boolean; - endCursor: string | null; startCursor: string | null; } export interface ProductListResult { - products: ProductCard[]; - totalCount: number; - pageInfo: PageInfo; filters?: Filter[]; + pageInfo: PageInfo; priceRange?: PriceRange; + products: ProductCard[]; subcategories?: CategoryNavItem[]; + totalCount: number; } export interface PredictiveSearchProduct { - id: string; - handle: string; - title: string; + availableForSale: boolean; + compareAtPrice?: Money; featuredImage: Image | null; + handle: string; + id: string; price: Money; - compareAtPrice?: Money; + title: string; vendor?: string; - availableForSale: boolean; } export interface SearchSuggestion { - text: string; styledText: string; + text: string; } export interface PredictiveSearchCollection { @@ -264,29 +264,29 @@ export interface PredictiveSearchCollection { } export interface PredictiveSearchResult { - products: PredictiveSearchProduct[]; collections: PredictiveSearchCollection[]; + products: PredictiveSearchProduct[]; queries: SearchSuggestion[]; } export interface MarketingImage { - url: string; alt: string; - width?: number; height?: number; + url: string; + width?: number; } export interface MarketingVideo { - url: string; previewImage?: MarketingImage | null; + url: string; } export interface BannerSection { - id: string; - headline: string; - subheadline: string | null; backgroundImage?: MarketingImage | StaticImageData | null; backgroundVideo?: MarketingVideo | null; - ctaText: string | null; ctaLink: string | null; + ctaText: string | null; + headline: string; + id: string; + subheadline: string | null; } From 736eb70aa4a87c85a3884ca7a645e7b96997cb2a Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 10:32:29 -0500 Subject: [PATCH 03/13] Bumps dependencies --- apps/docs/package.json | 12 +- apps/template/package.json | 12 +- pnpm-lock.yaml | 486 ++++++++++++++++++------------------- 3 files changed, 255 insertions(+), 255 deletions(-) diff --git a/apps/docs/package.json b/apps/docs/package.json index 2e1b234c..4385fedd 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -12,7 +12,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@ai-sdk/react": "3.0.195", + "@ai-sdk/react": "3.0.199", "@icons-pack/react-simple-icons": "13.13.0", "@streamdown/cjk": "1.0.3", "@streamdown/code": "1.1.1", @@ -24,7 +24,7 @@ "@types/react-dom": "19.2.3", "@vercel/analytics": "2.0.1", "@vercel/speed-insights": "2.0.0", - "ai": "6.0.193", + "ai": "6.0.197", "class-variance-authority": "0.7.1", "clsx": "2.1.1", "cmdk": "1.1.1", @@ -32,7 +32,7 @@ "dexie-react-hooks": "4.4.0", "feed": "5.2.1", "fromsrc": "0.0.31", - "geist": "1.7.0", + "geist": "1.7.2", "jotai": "2.20.0", "lucide-react": "1.17.0", "motion": "12.40.0", @@ -40,8 +40,8 @@ "next": "16.3.0-canary.42", "next-mdx-remote": "6.0.0", "next-themes": "0.4.6", - "oxfmt": "0.52.0", - "oxlint": "1.67.0", + "oxfmt": "0.53.0", + "oxlint": "1.68.0", "postcss": "8.5.15", "radix-ui": "1.4.3", "react": "19.2.7", @@ -54,7 +54,7 @@ "tailwindcss": "4.3.0", "tw-animate-css": "1.4.0", "typescript": "6.0.3", - "use-stick-to-bottom": "1.1.4", + "use-stick-to-bottom": "1.1.6", "vaul": "1.1.2", "zod": "4.4.3" } diff --git a/apps/template/package.json b/apps/template/package.json index 9bc4cb95..60dc873f 100644 --- a/apps/template/package.json +++ b/apps/template/package.json @@ -11,7 +11,7 @@ "start": "next start" }, "dependencies": { - "@ai-sdk/react": "3.0.195", + "@ai-sdk/react": "3.0.199", "@json-render/core": "0.19.0", "@json-render/react": "0.19.0", "@tailwindcss/postcss": "4.3.0", @@ -21,9 +21,9 @@ "@types/react-dom": "19.2.3", "@vercel/analytics": "2.0.1", "@vercel/speed-insights": "2.0.0", - "ai": "6.0.193", + "ai": "6.0.197", "babel-plugin-react-compiler": "1.0.0", - "better-auth": "1.6.12", + "better-auth": "1.6.14", "class-variance-authority": "0.7.1", "clsx": "2.1.1", "cmdk": "1.1.1", @@ -31,8 +31,8 @@ "nanoid": "5.1.11", "next": "16.3.0-canary.42", "next-intl": "4.13.0", - "oxfmt": "0.52.0", - "oxlint": "1.67.0", + "oxfmt": "0.53.0", + "oxlint": "1.68.0", "postcss": "8.5.15", "radix-ui": "1.4.3", "react": "19.2.7", @@ -43,7 +43,7 @@ "tailwindcss": "4.3.0", "tw-animate-css": "1.4.0", "typescript": "6.0.3", - "use-stick-to-bottom": "1.1.4", + "use-stick-to-bottom": "1.1.6", "zod": "4.4.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 551ed9a6..c441eb32 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,8 +24,8 @@ importers: apps/docs: dependencies: '@ai-sdk/react': - specifier: 3.0.195 - version: 3.0.195(react@19.2.7)(zod@4.4.3) + specifier: 3.0.199 + version: 3.0.199(react@19.2.7)(zod@4.4.3) '@icons-pack/react-simple-icons': specifier: 13.13.0 version: 13.13.0(react@19.2.7) @@ -60,8 +60,8 @@ importers: specifier: 2.0.0 version: 2.0.0(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) ai: - specifier: 6.0.193 - version: 6.0.193(zod@4.4.3) + specifier: 6.0.197 + version: 6.0.197(zod@4.4.3) class-variance-authority: specifier: 0.7.1 version: 0.7.1 @@ -84,8 +84,8 @@ importers: specifier: 0.0.31 version: 0.0.31(@types/react@19.2.16)(katex@0.16.38)(mermaid@11.13.0)(next@16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7) geist: - specifier: 1.7.0 - version: 1.7.0(next@16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) + specifier: 1.7.2 + version: 1.7.2(next@16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) jotai: specifier: 2.20.0 version: 2.20.0(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@19.2.16)(react@19.2.7) @@ -108,11 +108,11 @@ importers: specifier: 0.4.6 version: 0.4.6(react-dom@19.2.7(react@19.2.7))(react@19.2.7) oxfmt: - specifier: 0.52.0 - version: 0.52.0 + specifier: 0.53.0 + version: 0.53.0 oxlint: - specifier: 1.67.0 - version: 1.67.0 + specifier: 1.68.0 + version: 1.68.0 postcss: specifier: 8.5.15 version: 8.5.15 @@ -150,8 +150,8 @@ importers: specifier: 6.0.3 version: 6.0.3 use-stick-to-bottom: - specifier: 1.1.4 - version: 1.1.4(react@19.2.7) + specifier: 1.1.6 + version: 1.1.6(react@19.2.7) vaul: specifier: 1.1.2 version: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) @@ -162,8 +162,8 @@ importers: apps/template: dependencies: '@ai-sdk/react': - specifier: 3.0.195 - version: 3.0.195(react@19.2.7)(zod@4.4.3) + specifier: 3.0.199 + version: 3.0.199(react@19.2.7)(zod@4.4.3) '@json-render/core': specifier: 0.19.0 version: 0.19.0(zod@4.4.3) @@ -192,14 +192,14 @@ importers: specifier: 2.0.0 version: 2.0.0(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) ai: - specifier: 6.0.193 - version: 6.0.193(zod@4.4.3) + specifier: 6.0.197 + version: 6.0.197(zod@4.4.3) babel-plugin-react-compiler: specifier: 1.0.0 version: 1.0.0 better-auth: - specifier: 1.6.12 - version: 1.6.12(@opentelemetry/api@1.9.0)(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) + specifier: 1.6.14 + version: 1.6.14(@opentelemetry/api@1.9.0)(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) class-variance-authority: specifier: 0.7.1 version: 0.7.1 @@ -222,11 +222,11 @@ importers: specifier: 4.13.0 version: 4.13.0(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(typescript@6.0.3) oxfmt: - specifier: 0.52.0 - version: 0.52.0 + specifier: 0.53.0 + version: 0.53.0 oxlint: - specifier: 1.67.0 - version: 1.67.0 + specifier: 1.68.0 + version: 1.68.0 postcss: specifier: 8.5.15 version: 8.5.15 @@ -258,16 +258,16 @@ importers: specifier: 6.0.3 version: 6.0.3 use-stick-to-bottom: - specifier: 1.1.4 - version: 1.1.4(react@19.2.7) + specifier: 1.1.6 + version: 1.1.6(react@19.2.7) zod: specifier: 4.4.3 version: 4.4.3 packages: - '@ai-sdk/gateway@3.0.121': - resolution: {integrity: sha512-uY248djJRxa5W68MHiyqO8WLdOeKQoRClGg7PVX/VPhVW8SJNM7/l5DcrA5WAM3YfQrLyNkgZa2VOu8T0t8LUw==} + '@ai-sdk/gateway@3.0.125': + resolution: {integrity: sha512-tocl7cUDoTpmhZqeW8XVKMMznZQwwQAEunF0VyNKmf64qt8NbMIAEiet/vRMzh7Jr9WcFeb6EZjmhLTP4Qx2Og==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -282,8 +282,8 @@ packages: resolution: {integrity: sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw==} engines: {node: '>=18'} - '@ai-sdk/react@3.0.195': - resolution: {integrity: sha512-+yIH84d4bBNzLKfaDDf4EocEH0XQKKNwNShxbrz5xAiJMNIPnWVWT9cyrSerYaGH3iNVS/g2io42PE4HNbc4RA==} + '@ai-sdk/react@3.0.199': + resolution: {integrity: sha512-0QmG6nd1iDTTWpWbQbE5qgSpEm0XkBvrOn1L1rSzBhG5+7BasckcjTF3CQMwUxdvozMMYRNOGXLQODs/1+a3NQ==} engines: {node: '>=18'} peerDependencies: react: ^18 || ~19.0.1 || ~19.1.2 || ^19.2.1 @@ -366,8 +366,8 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@better-auth/core@1.6.12': - resolution: {integrity: sha512-6mXtYSYfo6TvHHCZAZmfjvIQQtBDWzWzwy9iIWPEoede2lP2SuJzkfIQNuTtIGzZcn7a9iuzIm1jWDBzfnBARg==} + '@better-auth/core@1.6.14': + resolution: {integrity: sha512-12cA7tnR4Wyb3nLpPmeq/Id7QNB+4OhjbzuX7sIhqglgXGjyT5iiNpe2lx/8FF532sHC450Yx1850salCYbkzw==} peerDependencies: '@better-auth/utils': 0.4.1 '@better-fetch/fetch': 1.1.21 @@ -383,46 +383,46 @@ packages: '@opentelemetry/api': optional: true - '@better-auth/drizzle-adapter@1.6.12': - resolution: {integrity: sha512-g0sKQstvXHH70s+TjAXo86cNyWV60ahhJm1sow27RyW41U10vfBehOFinU3GPESyxl/fEr9D27rk3jdl6E3l3A==} + '@better-auth/drizzle-adapter@1.6.14': + resolution: {integrity: sha512-lYs1jDudriKYMXNcLFLAvEvOEKbeKBFdDciG4H8qZhV+3+yghGC3f/H5qtgTDc8mGBPV+2tEvVgYqReurOSmNw==} peerDependencies: - '@better-auth/core': ^1.6.12 + '@better-auth/core': ^1.6.14 '@better-auth/utils': 0.4.1 drizzle-orm: ^0.45.2 peerDependenciesMeta: drizzle-orm: optional: true - '@better-auth/kysely-adapter@1.6.12': - resolution: {integrity: sha512-KhPwPmLj+MoTVGV6goPfCYf/7Fuiy2Q37GEWhvQdoFjkYKbGo995OoghBVNBnAYOakYvTYjG0JebCfiETBVX3g==} + '@better-auth/kysely-adapter@1.6.14': + resolution: {integrity: sha512-A2+381gYADuZpgd98XQ39bnxLzbT03wnnDmSQIXp7XcE3hF093mGMk6rxlAhENVHH7JL2B0Tv2la2o6n+6ppyQ==} peerDependencies: - '@better-auth/core': ^1.6.12 + '@better-auth/core': ^1.6.14 '@better-auth/utils': 0.4.1 kysely: ^0.28.17 || ^0.29.0 peerDependenciesMeta: kysely: optional: true - '@better-auth/memory-adapter@1.6.12': - resolution: {integrity: sha512-flblsePBCcB0DA6hewAOupxyypNTQczZvkNYvRrsVlBDIh0+vHBU/dTjoDmuQnZ3egTdFNnMeC+VrNnqt/GFUg==} + '@better-auth/memory-adapter@1.6.14': + resolution: {integrity: sha512-frtBTozi8qsBlypxp33dkiIZT2IOMvix3oh2qTTcBkK11ISsRSTUUadl7DbwXri2AEoooShsH6PSAput920J3Q==} peerDependencies: - '@better-auth/core': ^1.6.12 + '@better-auth/core': ^1.6.14 '@better-auth/utils': 0.4.1 - '@better-auth/mongo-adapter@1.6.12': - resolution: {integrity: sha512-IeiHZN9PtIyiqYgTDlrmm8sYI++5p1OI49uWB7LHg2+touiaNUGe0uWYymQpw1zq1e8FJxKlwvOc5vw6nGrI6g==} + '@better-auth/mongo-adapter@1.6.14': + resolution: {integrity: sha512-meaZx712k9c0Cl6urwYZRNa3mAy3/leaYiSNt+hVaCOEPlgTDxzmYMNACvTTYXgh4eCpDVf5G7ZMEYBtejKQdw==} peerDependencies: - '@better-auth/core': ^1.6.12 + '@better-auth/core': ^1.6.14 '@better-auth/utils': 0.4.1 mongodb: ^6.0.0 || ^7.0.0 peerDependenciesMeta: mongodb: optional: true - '@better-auth/prisma-adapter@1.6.12': - resolution: {integrity: sha512-+GvU8vZ3aJUHDBuR5PxtU5OpPQS2T9ND7s2JYm63bD6rnYztLwEo8bwHL3BvsTwSvCjFHZCtsn1A+6qyoOzTMw==} + '@better-auth/prisma-adapter@1.6.14': + resolution: {integrity: sha512-9b9wSqhCthMmOYo0QdX+N/cOv+fNck/JE5CZQuuWwEJl5QeoYhCZesXjts5VfLAPMIf6vKw3QNBrn0SVMXXi2Q==} peerDependencies: - '@better-auth/core': ^1.6.12 + '@better-auth/core': ^1.6.14 '@better-auth/utils': 0.4.1 '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 prisma: ^5.0.0 || ^6.0.0 || ^7.0.0 @@ -432,10 +432,10 @@ packages: prisma: optional: true - '@better-auth/telemetry@1.6.12': - resolution: {integrity: sha512-g59qLPq9SROyku0X5tiZpXXiVrsbjB1QA6OctOt9svzj7NjCFBoCAO9QlBiOTUolo0l9CF6fLlc85PoBkY5RtA==} + '@better-auth/telemetry@1.6.14': + resolution: {integrity: sha512-ALi3cEx5eyrFY+TeAdhc1uq8FqJyGvzgvIo7GQZOqGqLZxHY9nte44WN++jBFGJJbsW3e4cgLj8dQK291s6wWQ==} peerDependencies: - '@better-auth/core': ^1.6.12 + '@better-auth/core': ^1.6.14 '@better-auth/utils': 0.4.1 '@better-fetch/fetch': 1.1.21 @@ -858,246 +858,246 @@ packages: resolution: {integrity: sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==} engines: {node: '>=14'} - '@oxfmt/binding-android-arm-eabi@0.52.0': - resolution: {integrity: sha512-17EMSJnQ9g+upVHrAUYDMfH5lvRKQ9Nvg8WtEoH72oDr1VpWz+7/o3tD97U1EToen2YAQ/68JmtDYkQUi20dfQ==} + '@oxfmt/binding-android-arm-eabi@0.53.0': + resolution: {integrity: sha512-XfVM8AmIovBTKXCt14Op5wbfcoM8418nttd+nhMgM3RAVaJg1MtJc73FyWfUt0oxLyBGVwfniNVUsbV/b3VmPg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxfmt/binding-android-arm64@0.52.0': - resolution: {integrity: sha512-A2G1IdwGEW2lLJkIxcvuirRH1CzSl/e0NX11zTlW1gvxJThfwbI/BEoaKrTNpm7M2FchvIf6guvIQU7d5iz+OQ==} + '@oxfmt/binding-android-arm64@0.53.0': + resolution: {integrity: sha512-btHDfXckwdf9zgyAVznfZkf+GVyB0I1m1hlvaOMRx2xoyz3hphfPX97s89J3wfCN8QBETLtk4lQUaeOkrMuQOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxfmt/binding-darwin-arm64@0.52.0': - resolution: {integrity: sha512-f9+bLvOYxy7NttCLFTvQ7afmqDOWY4wIP9xdvfj5trQ1qj6f2UFAGwZESlfsMjvJNTyRpXfIlOanCI9FOvoeQA==} + '@oxfmt/binding-darwin-arm64@0.53.0': + resolution: {integrity: sha512-k2RjMcSTkHjoOlsVGbL35JVzXL+oQco3GHPl/5kjebVF4oHNfE24In8F5isqBh9LBJucycWHKDXdGrCchdWcHQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxfmt/binding-darwin-x64@0.52.0': - resolution: {integrity: sha512-YSTB9sJ5nnQd/Q0ddHkgof0ZCHPAnWZT1IW2SJ8omz7CP7KluJhO1fNHrpqdxCtpztJwSs4hY1uAee35wKxxaw==} + '@oxfmt/binding-darwin-x64@0.53.0': + resolution: {integrity: sha512-65jIBE2H1l5SSs16fmv6/7b6sAx/WpvnsgDhVWK9qSjNFDUro7MPQ6q5UhpY7kl46yltfR046iAnxy/Bzqbiew==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxfmt/binding-freebsd-x64@0.52.0': - resolution: {integrity: sha512-NIrRNTTPCs4UbmVs0bxLSCDlLCtIRMJIXklNKaXa5Oj2/K1UIMBvgE8+uPVo01Io3N9HF0+GAX+aAHjUgZS7vA==} + '@oxfmt/binding-freebsd-x64@0.53.0': + resolution: {integrity: sha512-oYe1gkz7U49PCYrS9147d2fJZj8mDI4Di6AvlsU5fu9p+Tq8S7qqOMSZjUiVTLX8bXuSA9Lk/tIxuegVjkNYRA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxfmt/binding-linux-arm-gnueabihf@0.52.0': - resolution: {integrity: sha512-JXUCde8mn3GpgQouz2PXUokgy/uT1QrRJBL2s983VWcSQp62wTFYiNXgTKdeo1Jgbr0IgUnKKvzIk/YBlj/nVQ==} + '@oxfmt/binding-linux-arm-gnueabihf@0.53.0': + resolution: {integrity: sha512-ailB2vLzGi629tymdAb2VYJyEHref7oqGxP+tRBrtRBxQrb6NV55JMT7xtGZ8uTeG2+Y9zojqW4LhJYxQnz9Pg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxfmt/binding-linux-arm-musleabihf@0.52.0': - resolution: {integrity: sha512-psbUXaRZ+V8DaXz10Qf7LSHtdtdKAmC8fxXgeU608jjzrmWK4quamZMOpl6sf+dikoFHA85uE93Q0BqxrCdQrQ==} + '@oxfmt/binding-linux-arm-musleabihf@0.53.0': + resolution: {integrity: sha512-abh4mWBvOvD966sobqF7r103y2yYx7Rb4WGHLOS4+5igGqLbbPxS9aK5+45D6iUY7dWMsk3Muz9a8gUtufvqJA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxfmt/binding-linux-arm64-gnu@0.52.0': - resolution: {integrity: sha512-Jw7MgWUU9lcLCcy82updISP3EthTlfvAwR6gWNxPzqly7+fLvOi2gHQE9xXQjpqaVLm/8P+gOzlv9ODuoVlaaw==} + '@oxfmt/binding-linux-arm64-gnu@0.53.0': + resolution: {integrity: sha512-z73PvuhJ8qA+cDbaiqbtopHglA91U4+y5wn2sTJJrnpB957d5P33FEuyP3DQIFd7ofljmDmfVT4G0CVGHZaJWg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-arm64-musl@0.52.0': - resolution: {integrity: sha512-wZg6bLjDvh2KibyI3QFUYo8GTXneIFsd0JvehtvJiUmQ8WRPERgxd/VM4ctWb86U5FT1FkqgS8/wZKVB+AZScg==} + '@oxfmt/binding-linux-arm64-musl@0.53.0': + resolution: {integrity: sha512-I6bhOTroqc3ThrwZ89l2k3ivKuELhdPLbAcJhRNyjWvlgwb0vjRgEnVL1XLx5Jud04/ypNRZBykAWrSk6l/D+g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxfmt/binding-linux-ppc64-gnu@0.52.0': - resolution: {integrity: sha512-IngE8uxhNvxcMrLjZNDo9xNLY7rEK33AKnaMd2B46he1e/mz2CfcW6If/U1wUjdRZddm1QzQaciqZkuMkdh1FA==} + '@oxfmt/binding-linux-ppc64-gnu@0.53.0': + resolution: {integrity: sha512-w0p3JzB/PkkQjXALMJMqP9YfP3yq4w6zGsu5kezQmUnxRkN3b/Theg2l/nDgBsOcczxS3gL6Gam5XNAVrO6QJQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-riscv64-gnu@0.52.0': - resolution: {integrity: sha512-H3+DdFMv/efN3Efmhsv18jDrpiWWqKG7wsfAlQBqAt6z/E2Bx+TwEj2Nowe51CPOWB8/mFBC2dAMSgVFLvvowA==} + '@oxfmt/binding-linux-riscv64-gnu@0.53.0': + resolution: {integrity: sha512-mzBhF6k1Yq1K/dqDmVe/AAafnlJfEpx7yfUiksyeWXJk5iSzZqBSxcsa02zIytYgQFRZ7h6WPZfwHg/DoOE1Kw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-riscv64-musl@0.52.0': - resolution: {integrity: sha512-zji+1kb7lJKohSDjzC1IsS+K/cKRs1hdVf0ZH0VbdbiakmtLvN9twBoXo/k8VdjFax7kfo+DyPxS7vv52br1aw==} + '@oxfmt/binding-linux-riscv64-musl@0.53.0': + resolution: {integrity: sha512-AlFCpnRQhogQFzZXWbO6xB6/Udy745L+eQNmDPGg7G/OeWsYmJc4jZYfUN5pQg0reOPWSED2mOQqKZOJM1U8cA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxfmt/binding-linux-s390x-gnu@0.52.0': - resolution: {integrity: sha512-hcLBYedpCy7ToUvvBidWk7+11Yhg1oAZ4+6hKPic/mQI6NaqXJSXMps5nFlwUuX2ewhtLZZDPg63TI042qGKBg==} + '@oxfmt/binding-linux-s390x-gnu@0.53.0': + resolution: {integrity: sha512-XD4ulY4f1DWbuuZXAqxhVn+gdPmrhnmojWtFN78ctVoupmS845fGhsUrk1HZXKQI+iymbaiz9vAjPsghHNQ7Ag==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-x64-gnu@0.52.0': - resolution: {integrity: sha512-IDO2loXK2OtTOhSPchU9MW25mWL2QCDGdJbjN8MXKZVS80qXe5gMTwQWu/gMJ3juoBHbkuUZNB2N1LHzNT7DoA==} + '@oxfmt/binding-linux-x64-gnu@0.53.0': + resolution: {integrity: sha512-xg8KWX0QnxmYWRe60CgHYWXI0ZOtBbqTsXvWiWrcl2XUHJ3fht2QerOk2iWvylzX3zNT2GpvBRxGoR4d3sxPRQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-x64-musl@0.52.0': - resolution: {integrity: sha512-mAV2Hjn0SatJ+KoAzKUC3eJhdJ8wv+3m1KyuS0dTsbF0c5weq+QrCt/DRZZM+uj/XiKzCDEUKYsBF30e2qkcyw==} + '@oxfmt/binding-linux-x64-musl@0.53.0': + resolution: {integrity: sha512-MWExpYBGvl+pIvVB/gj/CcWlN2al8AizT7rUbtaYaWNoQkhWARM6W3qpgoCr72CYSN9PborzPmM5MIRe2BrNdA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxfmt/binding-openharmony-arm64@0.52.0': - resolution: {integrity: sha512-vd4npaUIwChxp7XzkqmepBWTT9YMcSe/NBApVGPC30/lLyOVaV3dvma1SKo03t8O73BPRAG7EyJzGlN5cJM5hQ==} + '@oxfmt/binding-openharmony-arm64@0.53.0': + resolution: {integrity: sha512-u4sajgO4nxgmJIgc/y2AqPhkdbOkQH8WugXpA1+pW0ESQhvGZ1oGq61Q4xMbJHJU1hFgtO18QNrcFYDPYH0gwQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxfmt/binding-win32-arm64-msvc@0.52.0': - resolution: {integrity: sha512-k2sz6gWQdMfh5HPpIS+Bw/0UEV/kaK2xuqJRrWL233sEHx9WLlsmvlPFM4HUNThkYbSN0U0vPW7LVKZWDS8hPQ==} + '@oxfmt/binding-win32-arm64-msvc@0.53.0': + resolution: {integrity: sha512-Yq9sOZoIOJ5xPjO0qOyHJS4CiPuTkB2en9auxZz7Ar2p5RaC7BzLyVVmAA7zz9/L9YnjjY1DwNxN+ivKXimN/A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxfmt/binding-win32-ia32-msvc@0.52.0': - resolution: {integrity: sha512-rhke69GTcArodLHpjMTfNnvjTEBryDeZcUCKK/VjXDMtfTULl6QRh0ymX5/hbCUv2WjYm9h/QbW++q2vE15gWQ==} + '@oxfmt/binding-win32-ia32-msvc@0.53.0': + resolution: {integrity: sha512-es1fVNZEkBqEcQtBpn19SYFgZF7FawlkCjkT/iImfEAus4gun8fBwB1E9hpV5LcR9B0DBNvRIXhW8BQk3JaE+Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxfmt/binding-win32-x64-msvc@0.52.0': - resolution: {integrity: sha512-q5xL7oeXkZdEtNZWBdvehJcmt+GRu9l2bK40yJs1jJXlqq+r0Hygb1rTjq+FM2o/2xyt4cufH6KRplHp3Jjsvw==} + '@oxfmt/binding-win32-x64-msvc@0.53.0': + resolution: {integrity: sha512-QFmJs2bEu9AO4O6qsmEaZNGi6dFq8N+rT8EHAAnZIq/B9SeJDUbc4DzVxQ48MfDsL7D3sCZzo37zuTuspcURgg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@oxlint/binding-android-arm-eabi@1.67.0': - resolution: {integrity: sha512-VrSi571rDv1N8HaEDM+DEX8nmT0y9jJo8tzzW13vsOWTx59xQczCIJx68n2zWOXRT5YKZsOZXp4qkHN/10x4mw==} + '@oxlint/binding-android-arm-eabi@1.68.0': + resolution: {integrity: sha512-wEdsIspexXLLMCPAEOcCuFLMt6aE3AzTuA/nQKLPRnoJ+EQTturmGheDkhHuuVHx0GbutjQ3JKmEn+Gz6Ag28Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxlint/binding-android-arm64@1.67.0': - resolution: {integrity: sha512-l6+NdYxMoRohix5r5bbigW16LPicceCwGcQ6LKKuE1kUdjgFfQolJjrJsQYPFetIs78Gxj/G/f5TEGoTCwj9nQ==} + '@oxlint/binding-android-arm64@1.68.0': + resolution: {integrity: sha512-6aZRNNXQTsYtgaus8HTb9nuCcsrQTlKXGnktwvwW0n/SooRWNxNb3925grDkC63aEYZuCIyOVLV16IdYIoC2aQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxlint/binding-darwin-arm64@1.67.0': - resolution: {integrity: sha512-jOzXxS1AxFxhImLIRbtGIMrEwaXcgMw3gR57WB1cRk8ai+vpr6726kxXqVvlNsrXtJ/FrmOm8RxlC0m8SW24Qg==} + '@oxlint/binding-darwin-arm64@1.68.0': + resolution: {integrity: sha512-lVTbsE3kO4bLpZELgjRZuAJc8kP98wb83yMXWH8gaPaFZ+cM2IDeZto4ByoUAYj0Mxv2rvw+A1ssZequSepVSg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxlint/binding-darwin-x64@1.67.0': - resolution: {integrity: sha512-3DFAVY94OqjIZHXIPz37yGRSWwOFTAqChQ64/M69GYLawzP0KiwdhDNfqdKKYT0bTR/DNxmMnQsj3ns+8+X/Lg==} + '@oxlint/binding-darwin-x64@1.68.0': + resolution: {integrity: sha512-nCmw2XrmQskjBUh/sfP5yKs93V68LijQgjd1cuuZ/q4SCARngLYs60/qqyzuMsg8QQ9KArDI98hxs/RDGE4KRQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxlint/binding-freebsd-x64@1.67.0': - resolution: {integrity: sha512-e4dDKZuLu8TR9DEBssWSDahlPgZBwojTTHZUvnjBRJfJJbpxYCjfjKfi0Z1+CSLMiJBwI2yCDtRM1XJQaARjmg==} + '@oxlint/binding-freebsd-x64@1.68.0': + resolution: {integrity: sha512-TI4ovQJliYE9V6e06cEv+qEI9uj7Ao65fmif4er4HD+aouyYyh0P31q2jh3KtqsOHHcQqv2PZ61TjJFLpBDGWQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxlint/binding-linux-arm-gnueabihf@1.67.0': - resolution: {integrity: sha512-BKytFdcQzbITV3xlnzDUDTEDtbUMCCiC4EaNTDZ4FyT8gdNvBC4gfiLucXp/sQl0XU3p7syTlorUWVVVBZab2g==} + '@oxlint/binding-linux-arm-gnueabihf@1.68.0': + resolution: {integrity: sha512-LcNnEi9g71Cmry5ZpLbKT+oVv+/zYG3hYVAbBBB5X85nOQZSk8l92CnDkxJMcxUg0NCnMCOFZuaVDlMyv4tYJw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm-musleabihf@1.67.0': - resolution: {integrity: sha512-XYAv0esBDX7BpTzRDjVX2Vdj+zndd8ll2dFQiaeQ6zTZr7A8GRDTN7fH3FP3jU+O0vCDx85oH/EtG7BzPgAXuw==} + '@oxlint/binding-linux-arm-musleabihf@1.68.0': + resolution: {integrity: sha512-OovHahL3FX4UaK+hgSf11llUx2vszqjSdQQ61Ck9InOEI/ptZoC4XSQJurITqItVvd53JSlmkLMeaNjM1PoQew==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm64-gnu@1.67.0': - resolution: {integrity: sha512-zizRMjA0i6u/2B0evgda04iycu+MoNuf1pBy6Eh+1CjC5wMEG7qN5zdDKTCvFc0KSYSDM9QTG3gjZHirgtQuKg==} + '@oxlint/binding-linux-arm64-gnu@1.68.0': + resolution: {integrity: sha512-YbzTglnHLzzi9zv5or8Ztz5fykAoZE8W9iM42/bOrF4HBSB6rJTqdLQWuoP76EHQw9DuKl76K1QmFlG29sPJXQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-arm64-musl@1.67.0': - resolution: {integrity: sha512-zB/Tf6sUjmmvvbva9Gj3JTJ8rJ9t4I8/U0o6vSRtd0DRIsIuyegBwJAzhSUFQHdMijIRJkW0exs/yBhpw2S20w==} + '@oxlint/binding-linux-arm64-musl@1.68.0': + resolution: {integrity: sha512-qVKtCZNic+OoNnOr/hCQAu22HSQzflI7Fsq/Blzkw02SnLuv163k3kfmrVpZjSBlUHgsRKj6WgQiw30d3SX02Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxlint/binding-linux-ppc64-gnu@1.67.0': - resolution: {integrity: sha512-kgU40Gt74CK0TCsF51KZymkIwN9U0BajKsMijB52zPqOeZU9NAHkA/NSQkZDHEaCakx42DxhXkODiAqf2b4Gug==} + '@oxlint/binding-linux-ppc64-gnu@1.68.0': + resolution: {integrity: sha512-zExyZ8ZOUuAyQ0y9jpTcyjKUz62YY9JhKPyVxzvjTpXzZ3ujdqiVwfPWDdnA1SsIOrxdtxHn7KErDHLWskFjXg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-gnu@1.67.0': - resolution: {integrity: sha512-tOYhkk/iaG9aD3FvGpBFd1Lrw0x0RaVoJBxjUkfNzS50rC5NS5BteNCwgr8A2zCdADrIIoze6D7u6U5Ic++/iQ==} + '@oxlint/binding-linux-riscv64-gnu@1.68.0': + resolution: {integrity: sha512-6C4MPuwewyDavA7sxM14wzgRi5GGL68HPIxRCdVyS75U4MDbpFVYzKO9WNR6KLKTMPq2pcz3THwo1sK2uiqngw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-musl@1.67.0': - resolution: {integrity: sha512-sEtywrPb+0b+tHYl1SDCrw903fiC4eyKoNqzP3v+f2JT3Xcv4NEYG+P8rj+eEnX7IWhqV/xj8/JmcmVj21CXaA==} + '@oxlint/binding-linux-riscv64-musl@1.68.0': + resolution: {integrity: sha512-bnZooVeHAcvA+dH0EDLgx+7HY/DRi6e0hFszg3P+OBatuUjV6EvfIyNIzWOusmqAVh4L6r21GGTZtiKE4iqM4Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxlint/binding-linux-s390x-gnu@1.67.0': - resolution: {integrity: sha512-BvR8Moa0zCLxroOx4vZaZN9nUfwAUpSTwjZdxZyKy4bv3PrzrXrxKR/ZQ0L9wNSvlPhnMJeZfa3q5w6ZCTuN6Q==} + '@oxlint/binding-linux-s390x-gnu@1.68.0': + resolution: {integrity: sha512-dIqnZnJSmHCMOUpUcWQOiV14o3DDPVx1DSsMaSzvdhNjC1tB1iEPZbdiMSCIEYbkgbsYznHXWqFdKL8WUB3F8g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-gnu@1.67.0': - resolution: {integrity: sha512-mm2cxM6fksOpq6l0uFws8BUGKAR4dNa/cZCn37Npq7PFbhD5HDJqWfnoIvTaeRKMy5XdS2tO0MA0qbHDrnXAAA==} + '@oxlint/binding-linux-x64-gnu@1.68.0': + resolution: {integrity: sha512-zc9lEnfV/HreDTY6gdMlZe+irkwHSxQ4/B1pS9GyK7RVaA5LxhoZY/w6/o2vIwLLEYiXQ5ujGxOM1ZazeFAAIA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-musl@1.67.0': - resolution: {integrity: sha512-WmbMuLapKyDlobMkXAaAL0Y+Uczh4LETfIfQsUpbId4Ip8Ai82/jqeYTOoUCkuuhBFapgqP253+d83tLKOksJg==} + '@oxlint/binding-linux-x64-musl@1.68.0': + resolution: {integrity: sha512-Dl5QEX0TCo/40Cdh1o1JdPS//+YiWqjC+Hrrya5OQmStZZr4svAFtdlqcpCrU9yq2Mo3vRVyO9B3h0dzD8s36Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxlint/binding-openharmony-arm64@1.67.0': - resolution: {integrity: sha512-9g/PqxYJelzzTAOR5Y+RiRqdeydhEuXv2KxNeFcAKQ7UsvnWSY1OP4MsuPMbTO2Pf70tz7mFhl1j13H3fyh+8g==} + '@oxlint/binding-openharmony-arm64@1.68.0': + resolution: {integrity: sha512-/qy6dOvi4S3/LeXq0l5BT5pRKPYA7oj3uKwJOAZOr5HRLL+HK6jdBynvWuXIA2wwfE01RzNYmbBdM7vwYx00sA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxlint/binding-win32-arm64-msvc@1.67.0': - resolution: {integrity: sha512-2VhwE6Gatb0vJGnN0TBuQMbKCOiZlSQ/zJvVWYLK4a9d4iDiJOen/yVQkGpmsJ90MuH66fzi0kEKI0jRQMDxGA==} + '@oxlint/binding-win32-arm64-msvc@1.68.0': + resolution: {integrity: sha512-fHNtVqPHSYE7UFDSLVFUjxQjnSVXxseNJmRW+XuP4pXXDwePdPda43NL7/BBCFTxHjycOc44JNDaOPtFDNui9A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxlint/binding-win32-ia32-msvc@1.67.0': - resolution: {integrity: sha512-EQ3VExXfeM1InbE5+JjufhZZTWy+kHUwgt3yZR7gQ47Je/mE0WspQPan0OJznh493L5anM210YNJtH1PXjTSFg==} + '@oxlint/binding-win32-ia32-msvc@1.68.0': + resolution: {integrity: sha512-NnKXr4Wgo4nps3erhrE0f8shBvBPZMHg72nDsvX0JyrRvsNiP3f1JNvbCKh+A6VFvpF7ZoJxu904P3cKMhvZnA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxlint/binding-win32-x64-msvc@1.67.0': - resolution: {integrity: sha512-bw24y+/1MHS4QDkons3YyHkPT9uCMoLHHgQhb+mb8NOjTYwub1CZ+K9Ngr8aO5DMrDrkqHwTzlTwFP2vS8Y/ZQ==} + '@oxlint/binding-win32-x64-msvc@1.68.0': + resolution: {integrity: sha512-zg5pA+84AlU6XHJ3ruiRxziO71QTrz8nLsk6u01JGS5+tL9/bnlakFiklFrcy4R1/V7ktWtaNitN3JZWmKnf6g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -2398,8 +2398,8 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - ai@6.0.193: - resolution: {integrity: sha512-VQOTOse8+X8kMtg61DNSXlYJzwOW4NjMLDJNk/qxClWsFe4oiyFJDHGGG1oezfGcFzuYuQe/8Z7r4kwiZWh2YQ==} + ai@6.0.197: + resolution: {integrity: sha512-U3KsjkqwQXGHC0u0VeUDqUaNaBS/uQc7v4Vj92Cjv5lPx5DIyRBQYk4Hipy5vwD9AQKIG8uRvdaN9R+pAvrtcQ==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -2441,8 +2441,8 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - better-auth@1.6.12: - resolution: {integrity: sha512-vJG8hB+zcayZEJgcWGTzP2XODZuf/WKViOtam+uhhQ9879yc7fDWAV9O4jSs+R28noSXIAaB3zhIMN3DaDO3cA==} + better-auth@1.6.14: + resolution: {integrity: sha512-c0/DvTQGDpgfj1knekCpQrg6PSWGDtfAtP7Ou6FkAhoE3RNnnIxLB5qKj6tRg53a1xsq93G6T68cNxrUZ7ZVmw==} peerDependencies: '@lynx-js/react': '*' '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 @@ -2967,8 +2967,8 @@ packages: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} - geist@1.7.0: - resolution: {integrity: sha512-ZaoiZwkSf0DwwB1ncdLKp+ggAldqxl5L1+SXaNIBGkPAqcu+xjVJLxlf3/S8vLt9UHx1xu5fz3lbzKCj5iOVdQ==} + geist@1.7.2: + resolution: {integrity: sha512-Gu5lDFa3pLRyoBlBPf0QIFHVdWAnpco7fS1bJm41jyLPFoguBgiubseUN2oLXMgqZ7uxAxDoXcHMhCY/fOTTgg==} peerDependencies: next: '>=13.2.0' @@ -3625,8 +3625,8 @@ packages: outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - oxfmt@0.52.0: - resolution: {integrity: sha512-nJlYM35F64zTDMecCNhoHNkf+D/eHv7xcjj9XDSj+bFAVtN93m7v8DQMdHd6nDG6Akf/kEYYHmDUBs2Dz27Sug==} + oxfmt@0.53.0: + resolution: {integrity: sha512-9cB5glS3Ip6NMuZ+6NYTao9FCWkDhRtPYCtR3QBu/NxHoFbgzzTvi41N4jxz/GqGfuLKspui1qb/LlSu2IbMcw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -3638,8 +3638,8 @@ packages: vite-plus: optional: true - oxlint@1.67.0: - resolution: {integrity: sha512-blwwaHPdoH8piQ5/z0KHeoHFR7FZgl12WluKJfu4qFLPkZl6mK04PkLE45Fw1NxfBRSlh40Gu7MkxHUw++ociQ==} + oxlint@1.68.0: + resolution: {integrity: sha512-dXcbq+xsmLrMy6T8d0euf3IYUfLmjHIE11pOxiUSi5LHkFZaYPv568R6sEjcavVpUxoaQe66UBuK4HEi74NxpA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -4155,8 +4155,8 @@ packages: '@types/react': optional: true - use-stick-to-bottom@1.1.4: - resolution: {integrity: sha512-2w/lydkrwhWMv1vCaEhYbzMDhgbwIodHpAHPV0/xKJErRkbjDEUe1EWmvr6Fwb+qhiERjc1EWgAEZaSaF69CpA==} + use-stick-to-bottom@1.1.6: + resolution: {integrity: sha512-z3Up8jYQGTkUCsGBnwg6/wj70KgXoW5Kz1AAc1j8MtQuYMBo6ZsdhrIXoegxa7gaMMilgQYyTohTrt3p94jHog==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -4255,7 +4255,7 @@ packages: snapshots: - '@ai-sdk/gateway@3.0.121(zod@4.4.3)': + '@ai-sdk/gateway@3.0.125(zod@4.4.3)': dependencies: '@ai-sdk/provider': 3.0.10 '@ai-sdk/provider-utils': 4.0.27(zod@4.4.3) @@ -4273,10 +4273,10 @@ snapshots: dependencies: json-schema: 0.4.0 - '@ai-sdk/react@3.0.195(react@19.2.7)(zod@4.4.3)': + '@ai-sdk/react@3.0.199(react@19.2.7)(zod@4.4.3)': dependencies: '@ai-sdk/provider-utils': 4.0.27(zod@4.4.3) - ai: 6.0.193(zod@4.4.3) + ai: 6.0.197(zod@4.4.3) react: 19.2.7 swr: 2.4.1(react@19.2.7) throttleit: 2.1.0 @@ -4404,7 +4404,7 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0)': + '@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0)': dependencies: '@better-auth/utils': 0.4.1 '@better-fetch/fetch': 1.1.21 @@ -4418,36 +4418,36 @@ snapshots: optionalDependencies: '@opentelemetry/api': 1.9.0 - '@better-auth/drizzle-adapter@1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)': + '@better-auth/drizzle-adapter@1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)': dependencies: - '@better-auth/core': 1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) + '@better-auth/core': 1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) '@better-auth/utils': 0.4.1 - '@better-auth/kysely-adapter@1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(kysely@0.28.17)': + '@better-auth/kysely-adapter@1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(kysely@0.28.17)': dependencies: - '@better-auth/core': 1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) + '@better-auth/core': 1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) '@better-auth/utils': 0.4.1 optionalDependencies: kysely: 0.28.17 - '@better-auth/memory-adapter@1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)': + '@better-auth/memory-adapter@1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)': dependencies: - '@better-auth/core': 1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) + '@better-auth/core': 1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) '@better-auth/utils': 0.4.1 - '@better-auth/mongo-adapter@1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)': + '@better-auth/mongo-adapter@1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)': dependencies: - '@better-auth/core': 1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) + '@better-auth/core': 1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) '@better-auth/utils': 0.4.1 - '@better-auth/prisma-adapter@1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)': + '@better-auth/prisma-adapter@1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)': dependencies: - '@better-auth/core': 1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) + '@better-auth/core': 1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) '@better-auth/utils': 0.4.1 - '@better-auth/telemetry@1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)': + '@better-auth/telemetry@1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)': dependencies: - '@better-auth/core': 1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) + '@better-auth/core': 1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) '@better-auth/utils': 0.4.1 '@better-fetch/fetch': 1.1.21 @@ -4931,118 +4931,118 @@ snapshots: '@opentelemetry/semantic-conventions@1.40.0': {} - '@oxfmt/binding-android-arm-eabi@0.52.0': + '@oxfmt/binding-android-arm-eabi@0.53.0': optional: true - '@oxfmt/binding-android-arm64@0.52.0': + '@oxfmt/binding-android-arm64@0.53.0': optional: true - '@oxfmt/binding-darwin-arm64@0.52.0': + '@oxfmt/binding-darwin-arm64@0.53.0': optional: true - '@oxfmt/binding-darwin-x64@0.52.0': + '@oxfmt/binding-darwin-x64@0.53.0': optional: true - '@oxfmt/binding-freebsd-x64@0.52.0': + '@oxfmt/binding-freebsd-x64@0.53.0': optional: true - '@oxfmt/binding-linux-arm-gnueabihf@0.52.0': + '@oxfmt/binding-linux-arm-gnueabihf@0.53.0': optional: true - '@oxfmt/binding-linux-arm-musleabihf@0.52.0': + '@oxfmt/binding-linux-arm-musleabihf@0.53.0': optional: true - '@oxfmt/binding-linux-arm64-gnu@0.52.0': + '@oxfmt/binding-linux-arm64-gnu@0.53.0': optional: true - '@oxfmt/binding-linux-arm64-musl@0.52.0': + '@oxfmt/binding-linux-arm64-musl@0.53.0': optional: true - '@oxfmt/binding-linux-ppc64-gnu@0.52.0': + '@oxfmt/binding-linux-ppc64-gnu@0.53.0': optional: true - '@oxfmt/binding-linux-riscv64-gnu@0.52.0': + '@oxfmt/binding-linux-riscv64-gnu@0.53.0': optional: true - '@oxfmt/binding-linux-riscv64-musl@0.52.0': + '@oxfmt/binding-linux-riscv64-musl@0.53.0': optional: true - '@oxfmt/binding-linux-s390x-gnu@0.52.0': + '@oxfmt/binding-linux-s390x-gnu@0.53.0': optional: true - '@oxfmt/binding-linux-x64-gnu@0.52.0': + '@oxfmt/binding-linux-x64-gnu@0.53.0': optional: true - '@oxfmt/binding-linux-x64-musl@0.52.0': + '@oxfmt/binding-linux-x64-musl@0.53.0': optional: true - '@oxfmt/binding-openharmony-arm64@0.52.0': + '@oxfmt/binding-openharmony-arm64@0.53.0': optional: true - '@oxfmt/binding-win32-arm64-msvc@0.52.0': + '@oxfmt/binding-win32-arm64-msvc@0.53.0': optional: true - '@oxfmt/binding-win32-ia32-msvc@0.52.0': + '@oxfmt/binding-win32-ia32-msvc@0.53.0': optional: true - '@oxfmt/binding-win32-x64-msvc@0.52.0': + '@oxfmt/binding-win32-x64-msvc@0.53.0': optional: true - '@oxlint/binding-android-arm-eabi@1.67.0': + '@oxlint/binding-android-arm-eabi@1.68.0': optional: true - '@oxlint/binding-android-arm64@1.67.0': + '@oxlint/binding-android-arm64@1.68.0': optional: true - '@oxlint/binding-darwin-arm64@1.67.0': + '@oxlint/binding-darwin-arm64@1.68.0': optional: true - '@oxlint/binding-darwin-x64@1.67.0': + '@oxlint/binding-darwin-x64@1.68.0': optional: true - '@oxlint/binding-freebsd-x64@1.67.0': + '@oxlint/binding-freebsd-x64@1.68.0': optional: true - '@oxlint/binding-linux-arm-gnueabihf@1.67.0': + '@oxlint/binding-linux-arm-gnueabihf@1.68.0': optional: true - '@oxlint/binding-linux-arm-musleabihf@1.67.0': + '@oxlint/binding-linux-arm-musleabihf@1.68.0': optional: true - '@oxlint/binding-linux-arm64-gnu@1.67.0': + '@oxlint/binding-linux-arm64-gnu@1.68.0': optional: true - '@oxlint/binding-linux-arm64-musl@1.67.0': + '@oxlint/binding-linux-arm64-musl@1.68.0': optional: true - '@oxlint/binding-linux-ppc64-gnu@1.67.0': + '@oxlint/binding-linux-ppc64-gnu@1.68.0': optional: true - '@oxlint/binding-linux-riscv64-gnu@1.67.0': + '@oxlint/binding-linux-riscv64-gnu@1.68.0': optional: true - '@oxlint/binding-linux-riscv64-musl@1.67.0': + '@oxlint/binding-linux-riscv64-musl@1.68.0': optional: true - '@oxlint/binding-linux-s390x-gnu@1.67.0': + '@oxlint/binding-linux-s390x-gnu@1.68.0': optional: true - '@oxlint/binding-linux-x64-gnu@1.67.0': + '@oxlint/binding-linux-x64-gnu@1.68.0': optional: true - '@oxlint/binding-linux-x64-musl@1.67.0': + '@oxlint/binding-linux-x64-musl@1.68.0': optional: true - '@oxlint/binding-openharmony-arm64@1.67.0': + '@oxlint/binding-openharmony-arm64@1.68.0': optional: true - '@oxlint/binding-win32-arm64-msvc@1.67.0': + '@oxlint/binding-win32-arm64-msvc@1.68.0': optional: true - '@oxlint/binding-win32-ia32-msvc@1.67.0': + '@oxlint/binding-win32-ia32-msvc@1.68.0': optional: true - '@oxlint/binding-win32-x64-msvc@1.67.0': + '@oxlint/binding-win32-x64-msvc@1.68.0': optional: true '@parcel/watcher-android-arm64@2.5.6': @@ -6336,9 +6336,9 @@ snapshots: acorn@8.16.0: {} - ai@6.0.193(zod@4.4.3): + ai@6.0.197(zod@4.4.3): dependencies: - '@ai-sdk/gateway': 3.0.121(zod@4.4.3) + '@ai-sdk/gateway': 3.0.125(zod@4.4.3) '@ai-sdk/provider': 3.0.10 '@ai-sdk/provider-utils': 4.0.27(zod@4.4.3) '@opentelemetry/api': 1.9.0 @@ -6370,15 +6370,15 @@ snapshots: baseline-browser-mapping@2.10.7: {} - better-auth@1.6.12(@opentelemetry/api@1.9.0)(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)): + better-auth@1.6.14(@opentelemetry/api@1.9.0)(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)): dependencies: - '@better-auth/core': 1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) - '@better-auth/drizzle-adapter': 1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1) - '@better-auth/kysely-adapter': 1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(kysely@0.28.17) - '@better-auth/memory-adapter': 1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1) - '@better-auth/mongo-adapter': 1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1) - '@better-auth/prisma-adapter': 1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1) - '@better-auth/telemetry': 1.6.12(@better-auth/core@1.6.12(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21) + '@better-auth/core': 1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) + '@better-auth/drizzle-adapter': 1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1) + '@better-auth/kysely-adapter': 1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(kysely@0.28.17) + '@better-auth/memory-adapter': 1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1) + '@better-auth/mongo-adapter': 1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1) + '@better-auth/prisma-adapter': 1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1) + '@better-auth/telemetry': 1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21) '@better-auth/utils': 0.4.1 '@better-fetch/fetch': 1.1.21 '@noble/ciphers': 2.2.0 @@ -6887,7 +6887,7 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 - geist@1.7.0(next@16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)): + geist@1.7.2(next@16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)): dependencies: next: 16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) @@ -7852,51 +7852,51 @@ snapshots: outdent@0.5.0: {} - oxfmt@0.52.0: + oxfmt@0.53.0: dependencies: tinypool: 2.1.0 optionalDependencies: - '@oxfmt/binding-android-arm-eabi': 0.52.0 - '@oxfmt/binding-android-arm64': 0.52.0 - '@oxfmt/binding-darwin-arm64': 0.52.0 - '@oxfmt/binding-darwin-x64': 0.52.0 - '@oxfmt/binding-freebsd-x64': 0.52.0 - '@oxfmt/binding-linux-arm-gnueabihf': 0.52.0 - '@oxfmt/binding-linux-arm-musleabihf': 0.52.0 - '@oxfmt/binding-linux-arm64-gnu': 0.52.0 - '@oxfmt/binding-linux-arm64-musl': 0.52.0 - '@oxfmt/binding-linux-ppc64-gnu': 0.52.0 - '@oxfmt/binding-linux-riscv64-gnu': 0.52.0 - '@oxfmt/binding-linux-riscv64-musl': 0.52.0 - '@oxfmt/binding-linux-s390x-gnu': 0.52.0 - '@oxfmt/binding-linux-x64-gnu': 0.52.0 - '@oxfmt/binding-linux-x64-musl': 0.52.0 - '@oxfmt/binding-openharmony-arm64': 0.52.0 - '@oxfmt/binding-win32-arm64-msvc': 0.52.0 - '@oxfmt/binding-win32-ia32-msvc': 0.52.0 - '@oxfmt/binding-win32-x64-msvc': 0.52.0 - - oxlint@1.67.0: + '@oxfmt/binding-android-arm-eabi': 0.53.0 + '@oxfmt/binding-android-arm64': 0.53.0 + '@oxfmt/binding-darwin-arm64': 0.53.0 + '@oxfmt/binding-darwin-x64': 0.53.0 + '@oxfmt/binding-freebsd-x64': 0.53.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.53.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.53.0 + '@oxfmt/binding-linux-arm64-gnu': 0.53.0 + '@oxfmt/binding-linux-arm64-musl': 0.53.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.53.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.53.0 + '@oxfmt/binding-linux-riscv64-musl': 0.53.0 + '@oxfmt/binding-linux-s390x-gnu': 0.53.0 + '@oxfmt/binding-linux-x64-gnu': 0.53.0 + '@oxfmt/binding-linux-x64-musl': 0.53.0 + '@oxfmt/binding-openharmony-arm64': 0.53.0 + '@oxfmt/binding-win32-arm64-msvc': 0.53.0 + '@oxfmt/binding-win32-ia32-msvc': 0.53.0 + '@oxfmt/binding-win32-x64-msvc': 0.53.0 + + oxlint@1.68.0: optionalDependencies: - '@oxlint/binding-android-arm-eabi': 1.67.0 - '@oxlint/binding-android-arm64': 1.67.0 - '@oxlint/binding-darwin-arm64': 1.67.0 - '@oxlint/binding-darwin-x64': 1.67.0 - '@oxlint/binding-freebsd-x64': 1.67.0 - '@oxlint/binding-linux-arm-gnueabihf': 1.67.0 - '@oxlint/binding-linux-arm-musleabihf': 1.67.0 - '@oxlint/binding-linux-arm64-gnu': 1.67.0 - '@oxlint/binding-linux-arm64-musl': 1.67.0 - '@oxlint/binding-linux-ppc64-gnu': 1.67.0 - '@oxlint/binding-linux-riscv64-gnu': 1.67.0 - '@oxlint/binding-linux-riscv64-musl': 1.67.0 - '@oxlint/binding-linux-s390x-gnu': 1.67.0 - '@oxlint/binding-linux-x64-gnu': 1.67.0 - '@oxlint/binding-linux-x64-musl': 1.67.0 - '@oxlint/binding-openharmony-arm64': 1.67.0 - '@oxlint/binding-win32-arm64-msvc': 1.67.0 - '@oxlint/binding-win32-ia32-msvc': 1.67.0 - '@oxlint/binding-win32-x64-msvc': 1.67.0 + '@oxlint/binding-android-arm-eabi': 1.68.0 + '@oxlint/binding-android-arm64': 1.68.0 + '@oxlint/binding-darwin-arm64': 1.68.0 + '@oxlint/binding-darwin-x64': 1.68.0 + '@oxlint/binding-freebsd-x64': 1.68.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.68.0 + '@oxlint/binding-linux-arm-musleabihf': 1.68.0 + '@oxlint/binding-linux-arm64-gnu': 1.68.0 + '@oxlint/binding-linux-arm64-musl': 1.68.0 + '@oxlint/binding-linux-ppc64-gnu': 1.68.0 + '@oxlint/binding-linux-riscv64-gnu': 1.68.0 + '@oxlint/binding-linux-riscv64-musl': 1.68.0 + '@oxlint/binding-linux-s390x-gnu': 1.68.0 + '@oxlint/binding-linux-x64-gnu': 1.68.0 + '@oxlint/binding-linux-x64-musl': 1.68.0 + '@oxlint/binding-openharmony-arm64': 1.68.0 + '@oxlint/binding-win32-arm64-msvc': 1.68.0 + '@oxlint/binding-win32-ia32-msvc': 1.68.0 + '@oxlint/binding-win32-x64-msvc': 1.68.0 p-filter@2.1.0: dependencies: @@ -8520,7 +8520,7 @@ snapshots: optionalDependencies: '@types/react': 19.2.16 - use-stick-to-bottom@1.1.4(react@19.2.7): + use-stick-to-bottom@1.1.6(react@19.2.7): dependencies: react: 19.2.7 From 03373ae83c25faa732294530f3c92335ded1cbef Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 11:42:22 -0500 Subject: [PATCH 04/13] [template] robots: guard faceted (sort/filter) collection URLs (#321) Co-authored-by: Claude Opus 4.7 --- apps/docs/content/docs/anatomy/aeo-geo.mdx | 2 +- apps/template/app/robots.ts | 4 ++ ...07-robots-guard-faceted-collection-urls.md | 55 +++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 packages/plugin/template-rollout-log/2026-06-07-robots-guard-faceted-collection-urls.md diff --git a/apps/docs/content/docs/anatomy/aeo-geo.mdx b/apps/docs/content/docs/anatomy/aeo-geo.mdx index 97354a8a..7a02fdfe 100644 --- a/apps/docs/content/docs/anatomy/aeo-geo.mdx +++ b/apps/docs/content/docs/anatomy/aeo-geo.mdx @@ -17,7 +17,7 @@ The template ships with several built-in surfaces that contribute to AEO/GEO. Th | **Content negotiation** | Serves clean markdown to AI clients via `Accept: text/markdown` | `next.config.ts`, `app/md/**`, `lib/markdown/**` | | **Schema.org JSON-LD** | Embeds structured `Product`, `BreadcrumbList`, and `Organization` data | `components/product-detail/schema.tsx`, `components/schema/**` | | **Sitemap** | Enumerates products, collections, and pages for crawlers | `app/sitemap.ts`, `lib/shopify/operations/sitemap.ts` | -| **Robots** | Declares crawl policy, including allowances for known AI user agents | `app/robots.ts` | +| **Robots** | Declares crawl policy and blocks faceted (sort/filter) collection URLs | `app/robots.ts` | | **OpenGraph & Twitter metadata** | Provides title, description, and image previews per route | `lib/seo.ts`, route-level `generateMetadata` | The rest of this page goes deep on content negotiation. The other surfaces are documented inline in the linked files. diff --git a/apps/template/app/robots.ts b/apps/template/app/robots.ts index dd00bc2b..dcb849a0 100644 --- a/apps/template/app/robots.ts +++ b/apps/template/app/robots.ts @@ -17,6 +17,10 @@ export default function robots(): MetadataRoute.Robots { "/*/account", "/*/login", "/*/search", + "/collections/*?*sort=", + "/collections/*?*filter.", + "/*/collections/*?*sort=", + "/*/collections/*?*filter.", ], }, ], diff --git a/packages/plugin/template-rollout-log/2026-06-07-robots-guard-faceted-collection-urls.md b/packages/plugin/template-rollout-log/2026-06-07-robots-guard-faceted-collection-urls.md new file mode 100644 index 00000000..c4498a31 --- /dev/null +++ b/packages/plugin/template-rollout-log/2026-06-07-robots-guard-faceted-collection-urls.md @@ -0,0 +1,55 @@ +--- +title: Guard faceted collection URLs in robots +changeKey: robots-guard-faceted-collection-urls +introducedInVersion: 0.1.0 +introducedOn: 2026-06-07 +changeType: feature +defaultAction: adopt +appliesTo: + - all +paths: + - apps/template/app/robots.ts +--- + +## Summary + +Adds four `disallow` rules to `apps/template/app/robots.ts` that block crawlers from +sorted and filtered collection URLs: + +```ts +"/collections/*?*sort=", +"/collections/*?*filter.", +"/*/collections/*?*sort=", +"/*/collections/*?*filter.", +``` + +Bare collection URLs (`/collections/`) stay crawlable; only `?sort=` and +`?filter.*` variants are blocked. The `*?*marker` shape matches the param in any query +position. Locale-prefixed variants (`/*/collections/...`) mirror the existing prefixed +rules for when Markets/i18n routing is enabled. + +## Why it matters + +Each sort option crossed with each filter value is a distinct URL serving near-duplicate +content. Left open, crawlers burn budget on thousands of permutations and dilute ranking +signals — the same crawl-explosion problem Shopify Hydrogen guards against. `/search` was +already fully disallowed, so collection facets were the remaining unguarded surface. + +## Apply when + +Storefront exposes sort/filter via `sort=` and `filter.*` query params on `/collections/*` +(the template default). This is the canonical faceting scheme in `lib/utils.ts` and +`lib/shopify/operations/products.ts`. + +## Safe to skip when + +Storefront has renamed the sort/filter query params, or intentionally wants faceted +collection URLs indexed (e.g. curated landing pages built on filter combinations) — in +that case adjust the param markers rather than dropping the rules wholesale. + +## Validation + +1. `pnpm --filter template lint` passes. +2. `pnpm --filter template build` succeeds. +3. `curl http://localhost:3000/robots.txt` shows the four new `Disallow:` lines under + `User-agent: *`, with the `Sitemap:` line intact. From d5c4a3baca2fb82b7a01c1a6f775d79653f9dc0c Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 14:04:20 -0500 Subject: [PATCH 05/13] [docs] auth: correct Shopify Customer Account API setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Credentials come from the Headless sales channel (not Settings → Customer accounts), the client must be Confidential since the template uses a client secret, and the better-auth genericOAuth callback path is /api/auth/oauth2/callback/shopify. Co-Authored-By: Claude Opus 4.7 --- apps/docs/content/docs/anatomy/authentication.mdx | 15 ++++++++------- apps/docs/content/docs/reference/env-vars.mdx | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/docs/content/docs/anatomy/authentication.mdx b/apps/docs/content/docs/anatomy/authentication.mdx index 6e71e083..6dacaab2 100644 --- a/apps/docs/content/docs/anatomy/authentication.mdx +++ b/apps/docs/content/docs/anatomy/authentication.mdx @@ -24,12 +24,13 @@ Generate the auth secret with `openssl rand -base64 32`. The client ID and secre ### Shopify Admin setup -1. Go to **Shopify Admin → Settings → Customer accounts** -2. Enable **Customer Account API** -3. Create a **Customer Account API client** (under "API clients") -4. Set the redirect URI to `{YOUR_DOMAIN}/api/auth/callback/shopify` -5. Copy the client ID and client secret to your environment variables -6. Ensure the store domain matches `SHOPIFY_STORE_DOMAIN` +1. Enable customer accounts: **Shopify Admin → Settings → Customer accounts → Edit**, choose **Customer accounts**, and Save +2. Install the **Headless** sales channel from the Shopify App Store — Customer Account API credentials live there, not under Settings +3. Go to **Sales channels → Headless → (your storefront) → Customer Account API** +4. Set the client type to **Confidential** — the template authenticates with a client secret, so a public (PKCE-only) client will not work. The toggle is at the top of the Customer Account API settings +5. Set the redirect URI to `{YOUR_DOMAIN}/api/auth/oauth2/callback/shopify` +6. Copy the client ID and client secret to `SHOPIFY_CUSTOMER_CLIENT_ID` and `SHOPIFY_CUSTOMER_CLIENT_SECRET` +7. Ensure the store domain matches `SHOPIFY_STORE_DOMAIN` See [Environment Variables](/docs/reference/env-vars) for the full variable reference. @@ -75,7 +76,7 @@ The account pages use a `(authenticated)` route group so the auth-gated layout a ### Session flow 1. Customer visits `/account/login` → auto-redirected to Shopify OIDC -2. After Shopify consent → redirected to `/api/auth/callback/shopify` +2. After Shopify consent → redirected to `/api/auth/oauth2/callback/shopify` 3. better-auth exchanges the code for tokens, decodes the ID token, and creates a session 4. Session stored in an `httpOnly` cookie with PKCE verification diff --git a/apps/docs/content/docs/reference/env-vars.mdx b/apps/docs/content/docs/reference/env-vars.mdx index 6d2325f9..da92cde8 100644 --- a/apps/docs/content/docs/reference/env-vars.mdx +++ b/apps/docs/content/docs/reference/env-vars.mdx @@ -28,8 +28,8 @@ Required when `NEXT_PUBLIC_ENABLE_AUTH="1"`. Powers built-in customer authentica | Variable | Description | | -------------------------------- | -------------------------------------------------------------------------------------------------------- | | `BETTER_AUTH_SECRET` | Secret for signing sessions. Generate with `openssl rand -base64 32`. | -| `SHOPIFY_CUSTOMER_CLIENT_ID` | Customer Account API client ID. Found in **Shopify Admin → Settings → Customer accounts → API clients**. | -| `SHOPIFY_CUSTOMER_CLIENT_SECRET` | Customer Account API client secret. Found in the same location as the client ID. | +| `SHOPIFY_CUSTOMER_CLIENT_ID` | Customer Account API client ID. Found in **Sales channels → Headless → Customer Account API**. | +| `SHOPIFY_CUSTOMER_CLIENT_SECRET` | Customer Account API client secret. Same location as the client ID; requires a **Confidential** client. | ## Optional From 66ba2e86f1de1abcab0f9afa3ddcfdcf541f3084 Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 15:13:47 -0500 Subject: [PATCH 06/13] [docs] auth: document logout behavior and SSO caveat Logout is local-only; the template does not call Shopify's OIDC end_session_endpoint, so the IdP session persists and a later sign-in can silently re-auth. Note the wildcard-free Logout URI requirement for implementing RP-initiated logout. Co-Authored-By: Claude Opus 4.7 --- apps/docs/content/docs/anatomy/authentication.mdx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/docs/content/docs/anatomy/authentication.mdx b/apps/docs/content/docs/anatomy/authentication.mdx index 6dacaab2..9d7eb0fb 100644 --- a/apps/docs/content/docs/anatomy/authentication.mdx +++ b/apps/docs/content/docs/anatomy/authentication.mdx @@ -80,6 +80,14 @@ The account pages use a `(authenticated)` route group so the auth-gated layout a 3. better-auth exchanges the code for tokens, decodes the ID token, and creates a session 4. Session stored in an `httpOnly` cookie with PKCE verification +### Logout + +Logout is **local-only**. `signOut()` (`lib/auth/client.ts`) calls better-auth's sign-out endpoint to clear the session cookie, then redirects to `/`. The template does **not** call Shopify's OIDC `end_session_endpoint`, so the customer's session at Shopify's identity provider is not terminated — better-auth's `genericOAuth` plugin has no RP-initiated logout support to do this automatically. + +The practical consequence: the storefront session ends, but a later **Sign in** can silently re-authenticate via SSO with no credential prompt. This is fine for most storefronts but surprising on a shared device. It also means the **Logout URI** configured in the Customer Account API settings is unused. + +To fully end the Shopify session, implement RP-initiated logout: redirect the customer to the provider's `end_session_endpoint` (from the OIDC discovery document) with `id_token_hint` and a `post_logout_redirect_uri`. That redirect URI must be registered exactly in the Customer Account API **Logout URI** setting — Shopify does not support wildcard logout URIs, so each one (including any preview domains) must be added explicitly. + ### Nav account icon The nav uses a fixed-size container (`size-5`) with the fallback icon rendered inline and the async `NavAccount` component positioned absolutely on top via Suspense. This ensures the icon space is always reserved and there is no layout shift when the Suspense boundary resolves. From 89ff9c83895bb5f1fad1069cf7e355536b0ac96b Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 16:04:09 -0500 Subject: [PATCH 07/13] [template] account: live Customer Account API for orders, addresses, profile Replace the stubbed account pages with live Shopify Customer Account API data: paginated order history, order detail, address CRUD, and editable profile. Adds a customerAccountFetch helper plus customer operations, transforms, domain types, and server actions. Updates the auth docs and adds a template-rollout-log entry. Co-Authored-By: Claude Opus 4.7 --- .../content/docs/anatomy/authentication.mdx | 37 +- .../(authenticated)/addresses/page.tsx | 25 +- .../(authenticated)/orders/[id]/page.tsx | 126 ++++++- .../account/(authenticated)/orders/page.tsx | 101 ++++- .../account/(authenticated)/profile/page.tsx | 46 +-- .../components/account/address-book.tsx | 286 ++++++++++++++ .../components/account/order-display.tsx | 22 ++ .../components/account/profile-form.tsx | 88 +++++ apps/template/lib/customer/action.ts | 156 ++++++++ apps/template/lib/i18n/messages/en.json | 37 +- apps/template/lib/shopify/fetch.ts | 52 +++ .../lib/shopify/operations/customer.ts | 353 ++++++++++++++++++ .../lib/shopify/transforms/customer.ts | 146 ++++++++ apps/template/lib/types.ts | 71 ++++ ...6-06-07-customer-account-api-operations.md | 72 ++++ 15 files changed, 1566 insertions(+), 52 deletions(-) create mode 100644 apps/template/components/account/address-book.tsx create mode 100644 apps/template/components/account/order-display.tsx create mode 100644 apps/template/components/account/profile-form.tsx create mode 100644 apps/template/lib/customer/action.ts create mode 100644 apps/template/lib/shopify/operations/customer.ts create mode 100644 apps/template/lib/shopify/transforms/customer.ts create mode 100644 packages/plugin/template-rollout-log/2026-06-07-customer-account-api-operations.md diff --git a/apps/docs/content/docs/anatomy/authentication.mdx b/apps/docs/content/docs/anatomy/authentication.mdx index 9d7eb0fb..e0cff093 100644 --- a/apps/docs/content/docs/anatomy/authentication.mdx +++ b/apps/docs/content/docs/anatomy/authentication.mdx @@ -60,14 +60,14 @@ This means auth infrastructure has zero runtime cost when disabled. Authentication uses Shopify-native URL paths: -| Route | Description | -| ---------------------- | --------------------------------------------------------------------- | -| `/account/login` | Auto-redirects to Shopify OIDC. Not indexed by search engines. | -| `/account` | Redirects to `/account/profile`. | -| `/account/profile` | Displays customer name and email. | -| `/account/orders` | Order history (scaffold — wire with Customer Account API operations). | -| `/account/orders/[id]` | Order detail (scaffold). | -| `/account/addresses` | Address book (scaffold). | +| Route | Description | +| ---------------------- | --------------------------------------------------------------------------- | +| `/account/login` | Auto-redirects to Shopify OIDC. Not indexed by search engines. | +| `/account` | Redirects to `/account/profile`. | +| `/account/profile` | View and edit the customer's name; email shown read-only. | +| `/account/orders` | Paginated order history (cursor-based, newest first). | +| `/account/orders/[id]` | Order detail: line items, totals, shipping address, and a status-page link. | +| `/account/addresses` | Address book with create, edit, delete, and default selection. | The account pages use a `(authenticated)` route group so the auth-gated layout applies to protected pages without blocking `/account/login`. @@ -120,6 +120,23 @@ function AccountMenu() { } ``` +### Account data + +The account pages read and write customer data through the Shopify Customer Account API — a separate GraphQL endpoint and schema from the Storefront API. + +| Module | Purpose | +| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `lib/shopify/fetch.ts` | `customerAccountFetch()` — POSTs to `https://{domain}/customer/api/{version}/graphql` with the customer's access token as the raw `Authorization` header (no `Bearer` prefix). | +| `lib/shopify/operations/customer.ts` | Queries (profile, orders, order detail, addresses) and mutations (address create/update/delete, profile update). Each call resolves the token via `requireSession()`. | +| `lib/shopify/transforms/customer.ts` | Maps Customer Account API responses to the provider-agnostic domain types in `lib/types.ts`. | +| `lib/customer/action.ts` | `"use server"` actions for the address and profile forms. They validate input, surface Shopify `userErrors`, and `revalidatePath` on success. | + +Order and profile pages are read-only server components wrapped in Suspense. Addresses and profile editing use client forms that call the server actions. Order requests are per-customer `POST`s, so responses are never shared across customers. + +Status values (`fulfillmentStatus`, `financialStatus`) are raw Shopify enums (e.g. `FULFILLED`, `PAID`); they're humanized at the display layer rather than stored in locale catalogs. + +> The address form collects ISO codes for country (`territoryCode`) and region (`zoneCode`) as plain text inputs. Storefronts that want country/region dropdowns can layer a picker on top — the underlying `CustomerAddressInput` is unchanged. + ## Guardrails - Never expose access tokens to the client — `getSession()` and `requireSession()` are server-only @@ -129,6 +146,6 @@ function AccountMenu() { - PKCE is enabled for the OAuth flow — never disable it - `isAuthEnabled` must read a `NEXT_PUBLIC_` variable — server-only env vars cause hydration mismatches with cache components. Don't replace it with an inline `process.env.BETTER_AUTH_SECRET` check -## Next steps +## Extending -The account pages are scaffolds. To populate them with real data, create Customer Account API operations in `lib/shopify/operations/customer.ts` for fetching profile, orders, and addresses using the access token from `requireSession()`. +To add more account data — store credit, subscriptions, draft orders, or richer order fields — add an operation in `lib/shopify/operations/customer.ts`, a transform in `lib/shopify/transforms/customer.ts`, and a matching domain type in `lib/types.ts`. Validate any new fields against the live Customer Account API schema before adding them. Mutations should run through a `"use server"` action in `lib/customer/action.ts` so input validation and `revalidatePath` stay in one place. diff --git a/apps/template/app/account/(authenticated)/addresses/page.tsx b/apps/template/app/account/(authenticated)/addresses/page.tsx index 2ee0322b..ce29bcd2 100644 --- a/apps/template/app/account/(authenticated)/addresses/page.tsx +++ b/apps/template/app/account/(authenticated)/addresses/page.tsx @@ -1,6 +1,10 @@ import { getTranslations } from "next-intl/server"; +import { Suspense } from "react"; +import { AddressBook } from "@/components/account/address-book"; import { AccountPageHeader } from "@/components/account/page-header"; +import { Skeleton } from "@/components/ui/skeleton"; +import { getCustomerAddresses } from "@/lib/shopify/operations/customer"; export default async function AddressesPage() { const t = await getTranslations("account"); @@ -8,9 +12,24 @@ export default async function AddressesPage() { return ( <> -
-

{t("noAddresses")}

-
+ }> + + ); } + +async function AddressesContent() { + const addresses = await getCustomerAddresses(); + return ; +} + +function AddressesSkeleton() { + return ( +
+ + + +
+ ); +} diff --git a/apps/template/app/account/(authenticated)/orders/[id]/page.tsx b/apps/template/app/account/(authenticated)/orders/[id]/page.tsx index 792ee114..d91c2447 100644 --- a/apps/template/app/account/(authenticated)/orders/[id]/page.tsx +++ b/apps/template/app/account/(authenticated)/orders/[id]/page.tsx @@ -1,29 +1,143 @@ import { getTranslations } from "next-intl/server"; +import Image from "next/image"; import { notFound } from "next/navigation"; import { Suspense } from "react"; +import { + formatOrderDate, + humanizeStatus, + OrderStatusBadge, +} from "@/components/account/order-display"; import { AccountPageHeader } from "@/components/account/page-header"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Skeleton } from "@/components/ui/skeleton"; +import { defaultLocale } from "@/lib/i18n"; +import { getCustomerOrder } from "@/lib/shopify/operations/customer"; +import type { Money, OrderLineItem } from "@/lib/types"; +import { formatPrice } from "@/lib/utils"; export default function OrderDetailPage({ params }: { params: Promise<{ id: string }> }) { return ( - + }> ); } async function OrderDetailContent({ params }: { params: Promise<{ id: string }> }) { - const { id } = await params; - const t = await getTranslations("account"); + const [{ id }, t] = await Promise.all([params, getTranslations("account")]); if (!id) notFound(); + const order = await getCustomerOrder(id); + if (!order) notFound(); + return ( <> - -
-

{t("orderDetailPlaceholder")}

+ + +
+ + {order.financialStatus ? ( + {humanizeStatus(order.financialStatus)} + ) : null} +
+ +
    + {order.lineItems.map((item, index) => ( + + ))} +
+ +
+ + + +
+
{t("total")}
+
+ {formatPrice( + Number(order.totalPrice.amount), + order.totalPrice.currencyCode, + defaultLocale, + )} +
+
+
+ + {order.shippingAddress && order.shippingAddress.formatted.length > 0 ? ( +
+

{t("shippingAddress")}

+
+ {order.shippingAddress.formatted.map((line, index) => ( + + {line} + + ))} +
+
+ ) : null} + + ); } + +function OrderLineItemRow({ item }: { item: OrderLineItem }) { + return ( +
  • +
    + {item.image ? ( + {item.image.altText} + ) : null} +
    +
    +

    {item.title}

    + {item.variantTitle ? ( +

    {item.variantTitle}

    + ) : null} +

    × {item.quantity}

    +
    + {item.totalPrice ? ( + + {formatPrice(Number(item.totalPrice.amount), item.totalPrice.currencyCode, defaultLocale)} + + ) : null} +
  • + ); +} + +function SummaryRow({ label, money }: { label: string; money: Money | null }) { + if (!money) return null; + return ( +
    +
    {label}
    +
    + {formatPrice(Number(money.amount), money.currencyCode, defaultLocale)} +
    +
    + ); +} + +function OrderDetailSkeleton() { + return ( +
    + + + +
    + ); +} diff --git a/apps/template/app/account/(authenticated)/orders/page.tsx b/apps/template/app/account/(authenticated)/orders/page.tsx index 6fb2e524..0c1b8720 100644 --- a/apps/template/app/account/(authenticated)/orders/page.tsx +++ b/apps/template/app/account/(authenticated)/orders/page.tsx @@ -1,16 +1,113 @@ import { getTranslations } from "next-intl/server"; +import Link from "next/link"; +import { Suspense } from "react"; +import { formatOrderDate, OrderStatusBadge } from "@/components/account/order-display"; import { AccountPageHeader } from "@/components/account/page-header"; +import { Button } from "@/components/ui/button"; +import { Skeleton } from "@/components/ui/skeleton"; +import { defaultLocale } from "@/lib/i18n"; +import { getCustomerOrders } from "@/lib/shopify/operations/customer"; +import { formatPrice } from "@/lib/utils"; -export default async function OrdersPage() { +export default async function OrdersPage({ + searchParams, +}: { + searchParams: Promise<{ after?: string; before?: string }>; +}) { const t = await getTranslations("account"); return ( <> + }> + + + + ); +} + +async function OrdersContent({ + searchParams, +}: { + searchParams: Promise<{ after?: string; before?: string }>; +}) { + const [params, t] = await Promise.all([searchParams, getTranslations("account")]); + const { orders, pageInfo } = await getCustomerOrders({ + after: params.after, + before: params.before, + }); + + if (orders.length === 0) { + return (

    {t("noOrders")}

    - + ); + } + + return ( +
    +
      + {orders.map((order) => ( +
    • + +
      + {order.name} + + {formatOrderDate(order.processedAt)} + +
      +
      + + + {formatPrice( + Number(order.totalPrice.amount), + order.totalPrice.currencyCode, + defaultLocale, + )} + +
      + +
    • + ))} +
    + + {pageInfo.hasNextPage || pageInfo.hasPreviousPage ? ( +
    + {pageInfo.hasPreviousPage && pageInfo.startCursor ? ( + + ) : ( + + )} + {pageInfo.hasNextPage && pageInfo.endCursor ? ( + + ) : ( + + )} +
    + ) : null} +
    + ); +} + +function OrdersSkeleton() { + return ( +
    + {Array.from({ length: 4 }).map((_, index) => ( + + ))} +
    ); } diff --git a/apps/template/app/account/(authenticated)/profile/page.tsx b/apps/template/app/account/(authenticated)/profile/page.tsx index 82213d74..d38e3da3 100644 --- a/apps/template/app/account/(authenticated)/profile/page.tsx +++ b/apps/template/app/account/(authenticated)/profile/page.tsx @@ -2,8 +2,9 @@ import { getTranslations } from "next-intl/server"; import { Suspense } from "react"; import { AccountPageHeader } from "@/components/account/page-header"; +import { ProfileForm } from "@/components/account/profile-form"; import { Skeleton } from "@/components/ui/skeleton"; -import { getCustomerSession } from "@/lib/auth/server"; +import { getCustomerProfile } from "@/lib/shopify/operations/customer"; export default async function ProfilePage() { const t = await getTranslations("account"); @@ -19,41 +20,30 @@ export default async function ProfilePage() { } async function ProfileContent() { - const [session, t] = await Promise.all([getCustomerSession(), getTranslations("account")]); + const profile = await getCustomerProfile(); + if (!profile) return null; - return ( -
    -
    -
    -
    -
    {t("name")}
    -
    - {[session?.firstName, session?.lastName].filter(Boolean).join(" ") || "-"} -
    -
    -
    -
    {t("email")}
    -
    {session?.email || "-"}
    -
    -
    -
    -
    - ); + return ; } function ProfileSkeleton() { return ( -
    -
    -
    - - +
    +
    +
    + +
    -
    - - +
    + +
    +
    + + +
    +
    ); } diff --git a/apps/template/components/account/address-book.tsx b/apps/template/components/account/address-book.tsx new file mode 100644 index 00000000..40f08608 --- /dev/null +++ b/apps/template/components/account/address-book.tsx @@ -0,0 +1,286 @@ +"use client"; + +import { Loader2, Pencil, Plus, Trash2 } from "lucide-react"; +import { useTranslations } from "next-intl"; +import { useState, useTransition } from "react"; + +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Switch } from "@/components/ui/switch"; +import { + createAddressAction, + deleteAddressAction, + updateAddressAction, +} from "@/lib/customer/action"; +import type { CustomerAddress, CustomerAddressInput } from "@/lib/types"; + +type FormState = { address: CustomerAddress; mode: "edit" } | { mode: "create" } | null; + +const TEXT_FIELDS = [ + { autoComplete: "given-name", key: "firstName", labelKey: "addressFirstName", span: false }, + { autoComplete: "family-name", key: "lastName", labelKey: "addressLastName", span: false }, + { autoComplete: "organization", key: "company", labelKey: "addressCompany", span: true }, + { autoComplete: "address-line1", key: "address1", labelKey: "addressLine1", span: true }, + { autoComplete: "address-line2", key: "address2", labelKey: "addressLine2", span: true }, + { autoComplete: "address-level2", key: "city", labelKey: "addressCity", span: false }, + { autoComplete: "address-level1", key: "zoneCode", labelKey: "addressZone", span: false }, + { autoComplete: "postal-code", key: "zip", labelKey: "addressZip", span: false }, + { autoComplete: "country", key: "territoryCode", labelKey: "addressCountry", span: false }, + { autoComplete: "tel", key: "phoneNumber", labelKey: "addressPhone", span: true }, +] as const satisfies readonly { + autoComplete: string; + key: keyof CustomerAddressInput; + labelKey: string; + span: boolean; +}[]; + +const REQUIRED_FIELDS = new Set(["address1", "city", "territoryCode"]); + +export function AddressBook({ addresses }: { addresses: CustomerAddress[] }) { + const t = useTranslations("account"); + const [formState, setFormState] = useState(null); + const [deleteTarget, setDeleteTarget] = useState(null); + + return ( +
    +
    + +
    + + {addresses.length === 0 ? ( +
    +

    {t("noAddresses")}

    +
    + ) : ( +
      + {addresses.map((address) => ( +
    • +
      +
      + {address.formatted.map((line, index) => ( + + {line} + + ))} +
      + {address.isDefault ? ( + {t("defaultAddress")} + ) : null} +
      +
      + + +
      +
    • + ))} +
    + )} + + !open && setFormState(null)}> + + + + {formState?.mode === "edit" ? t("editAddress") : t("addAddress")} + + + {formState !== null ? ( + setFormState(null)} + /> + ) : null} + + + + setDeleteTarget(null)} /> +
    + ); +} + +function AddressForm({ address, onSuccess }: { address?: CustomerAddress; onSuccess: () => void }) { + const t = useTranslations("account"); + const [values, setValues] = useState(() => toFormValues(address)); + const [isDefault, setIsDefault] = useState(address?.isDefault ?? false); + const [error, setError] = useState(null); + const [fieldErrors, setFieldErrors] = useState>({}); + const [isPending, startTransition] = useTransition(); + + const isCurrentDefault = address?.isDefault ?? false; + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setError(null); + setFieldErrors({}); + + startTransition(async () => { + const result = address + ? await updateAddressAction(address.id, values, isDefault) + : await createAddressAction(values, isDefault); + + if (result.success) { + onSuccess(); + } else { + setError(result.error ?? null); + setFieldErrors(result.fieldErrors ?? {}); + } + }); + }; + + return ( +
    +
    + {TEXT_FIELDS.map((field) => { + const fieldError = fieldErrors[field.key]; + return ( +
    + + + setValues((prev) => ({ ...prev, [field.key]: event.target.value })) + } + autoComplete={field.autoComplete} + required={REQUIRED_FIELDS.has(field.key)} + aria-invalid={fieldError ? true : undefined} + placeholder={ + field.key === "territoryCode" + ? t("addressCountryPlaceholder") + : field.key === "zoneCode" + ? t("addressZonePlaceholder") + : undefined + } + /> + {fieldError ? ( +

    + {fieldError} +

    + ) : null} +
    + ); + })} +
    + +
    + + +
    + + {error ? ( +

    + {error} +

    + ) : null} + + + + +
    + ); +} + +function DeleteDialog({ + onClose, + target, +}: { + onClose: () => void; + target: CustomerAddress | null; +}) { + const t = useTranslations("account"); + const [isPending, startTransition] = useTransition(); + const [error, setError] = useState(null); + + const handleDelete = () => { + if (!target) return; + setError(null); + startTransition(async () => { + const result = await deleteAddressAction(target.id); + if (result.success) { + onClose(); + } else { + setError(result.error ?? null); + } + }); + }; + + return ( + !open && onClose()}> + + + {t("deleteAddressTitle")} + {t("deleteAddressConfirm")} + + {error ? ( +

    + {error} +

    + ) : null} + + + + +
    +
    + ); +} + +function toFormValues(address?: CustomerAddress): CustomerAddressInput { + return { + address1: address?.address1 ?? "", + address2: address?.address2 ?? "", + city: address?.city ?? "", + company: address?.company ?? "", + firstName: address?.firstName ?? "", + lastName: address?.lastName ?? "", + phoneNumber: address?.phoneNumber ?? "", + territoryCode: address?.territoryCode ?? "", + zip: address?.zip ?? "", + zoneCode: address?.zoneCode ?? "", + }; +} diff --git a/apps/template/components/account/order-display.tsx b/apps/template/components/account/order-display.tsx new file mode 100644 index 00000000..879af3ec --- /dev/null +++ b/apps/template/components/account/order-display.tsx @@ -0,0 +1,22 @@ +import { Badge } from "@/components/ui/badge"; +import { defaultLocale } from "@/lib/i18n"; + +export function humanizeStatus(status: string): string { + return status + .toLowerCase() + .split("_") + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(" "); +} + +export function formatOrderDate(iso: string, locale: string = defaultLocale): string { + return new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(new Date(iso)); +} + +export function OrderStatusBadge({ status }: { status: string }) { + return ( + + {humanizeStatus(status)} + + ); +} diff --git a/apps/template/components/account/profile-form.tsx b/apps/template/components/account/profile-form.tsx new file mode 100644 index 00000000..259b6211 --- /dev/null +++ b/apps/template/components/account/profile-form.tsx @@ -0,0 +1,88 @@ +"use client"; + +import { Loader2 } from "lucide-react"; +import { useTranslations } from "next-intl"; +import { useState, useTransition } from "react"; + +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { updateProfileAction } from "@/lib/customer/action"; +import type { CustomerProfile } from "@/lib/types"; + +export function ProfileForm({ profile }: { profile: CustomerProfile }) { + const t = useTranslations("account"); + const [firstName, setFirstName] = useState(profile.firstName ?? ""); + const [lastName, setLastName] = useState(profile.lastName ?? ""); + const [error, setError] = useState(null); + const [saved, setSaved] = useState(false); + const [isPending, startTransition] = useTransition(); + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setError(null); + setSaved(false); + + startTransition(async () => { + const result = await updateProfileAction({ firstName, lastName }); + if (result.success) { + setSaved(true); + } else { + setError(result.error ?? null); + } + }); + }; + + return ( +
    +
    +
    + + { + setFirstName(event.target.value); + setSaved(false); + }} + autoComplete="given-name" + /> +
    +
    + + { + setLastName(event.target.value); + setSaved(false); + }} + autoComplete="family-name" + /> +
    +
    + +
    + + +
    + + {error ? ( +

    + {error} +

    + ) : null} + +
    + + {saved ? ( + {t("profileUpdated")} + ) : null} +
    +
    + ); +} diff --git a/apps/template/lib/customer/action.ts b/apps/template/lib/customer/action.ts new file mode 100644 index 00000000..6df062aa --- /dev/null +++ b/apps/template/lib/customer/action.ts @@ -0,0 +1,156 @@ +"use server"; + +import { revalidatePath } from "next/cache"; + +import { + createCustomerAddress, + type CustomerUserError, + deleteCustomerAddress, + updateCustomerAddress, + updateCustomerProfile, +} from "@/lib/shopify/operations/customer"; +import type { CustomerAddressInput } from "@/lib/types"; + +export interface AccountActionResult { + error?: string; + fieldErrors?: Record; + success: boolean; +} + +const MAX_FIELD_LENGTH = 255; +const MAX_NAME_LENGTH = 100; + +const ADDRESS_FIELDS = [ + "address1", + "address2", + "city", + "company", + "firstName", + "lastName", + "phoneNumber", + "territoryCode", + "zip", + "zoneCode", +] as const satisfies readonly (keyof CustomerAddressInput)[]; + +const UPPERCASE_FIELDS = new Set(["territoryCode", "zoneCode"]); + +// Customer Account API userErrors carry a `field` path like ["address", "zip"]; +// the last segment is the input field a form can highlight. +function mapUserErrors(errors: CustomerUserError[]): AccountActionResult { + if (errors.length === 0) return { success: true }; + + const fieldErrors: Record = {}; + for (const error of errors) { + const key = error.field?.at(-1); + if (key && !fieldErrors[key]) fieldErrors[key] = error.message; + } + + return { + success: false, + error: errors[0].message, + fieldErrors: Object.keys(fieldErrors).length > 0 ? fieldErrors : undefined, + }; +} + +function buildAddressInput(raw: CustomerAddressInput): CustomerAddressInput { + const input: CustomerAddressInput = {}; + + for (const field of ADDRESS_FIELDS) { + const value = raw[field]?.trim().slice(0, MAX_FIELD_LENGTH); + if (!value) continue; + input[field] = UPPERCASE_FIELDS.has(field) ? value.toUpperCase() : value; + } + + return input; +} + +function validateAddress(input: CustomerAddressInput): string | null { + if (!input.address1) return "Address is required"; + if (!input.city) return "City is required"; + if (!input.territoryCode) return "Country is required"; + return null; +} + +export async function createAddressAction( + raw: CustomerAddressInput, + isDefault: boolean, +): Promise { + const input = buildAddressInput(raw); + const validationError = validateAddress(input); + if (validationError) return { success: false, error: validationError }; + + try { + const result = mapUserErrors(await createCustomerAddress(input, isDefault)); + if (result.success) revalidatePath("/account/addresses"); + return result; + } catch (error) { + console.error("Create address failed:", error); + return { + success: false, + error: error instanceof Error ? error.message : "Failed to create address", + }; + } +} + +export async function updateAddressAction( + addressId: string, + raw: CustomerAddressInput, + isDefault: boolean, +): Promise { + if (!addressId) return { success: false, error: "Invalid address ID" }; + + const input = buildAddressInput(raw); + const validationError = validateAddress(input); + if (validationError) return { success: false, error: validationError }; + + try { + const result = mapUserErrors(await updateCustomerAddress(addressId, input, isDefault)); + if (result.success) revalidatePath("/account/addresses"); + return result; + } catch (error) { + console.error("Update address failed:", error); + return { + success: false, + error: error instanceof Error ? error.message : "Failed to update address", + }; + } +} + +export async function deleteAddressAction(addressId: string): Promise { + if (!addressId) return { success: false, error: "Invalid address ID" }; + + try { + const result = mapUserErrors(await deleteCustomerAddress(addressId)); + if (result.success) revalidatePath("/account/addresses"); + return result; + } catch (error) { + console.error("Delete address failed:", error); + return { + success: false, + error: error instanceof Error ? error.message : "Failed to delete address", + }; + } +} + +export async function updateProfileAction(raw: { + firstName: string; + lastName: string; +}): Promise { + const input = { + firstName: raw.firstName.trim().slice(0, MAX_NAME_LENGTH), + lastName: raw.lastName.trim().slice(0, MAX_NAME_LENGTH), + }; + + try { + const result = mapUserErrors(await updateCustomerProfile(input)); + if (result.success) revalidatePath("/account/profile"); + return result; + } catch (error) { + console.error("Update profile failed:", error); + return { + success: false, + error: error instanceof Error ? error.message : "Failed to update profile", + }; + } +} diff --git a/apps/template/lib/i18n/messages/en.json b/apps/template/lib/i18n/messages/en.json index 09683cb3..0d854c0b 100644 --- a/apps/template/lib/i18n/messages/en.json +++ b/apps/template/lib/i18n/messages/en.json @@ -3,19 +3,50 @@ "skipToContent": "Skip to content" }, "account": { + "addAddress": "Add address", + "addressCity": "City", + "addressCompany": "Company", + "addressCountry": "Country code", + "addressCountryPlaceholder": "e.g. US", "addresses": "Addresses", "addressesDescription": "Manage your saved addresses", + "addressFirstName": "First name", + "addressLastName": "Last name", + "addressLine1": "Address", + "addressLine2": "Apartment, suite, etc.", + "addressPhone": "Phone", + "addressZip": "ZIP / Postal code", + "addressZone": "State / Province code", + "addressZonePlaceholder": "e.g. CA", + "cancel": "Cancel", + "defaultAddress": "Default", + "delete": "Delete", + "deleteAddressConfirm": "This address will be permanently removed from your account.", + "deleteAddressTitle": "Delete address?", + "edit": "Edit", + "editAddress": "Edit address", "email": "Email", + "firstName": "First name", + "lastName": "Last name", "name": "Name", + "newerOrders": "Newer", "noAddresses": "You have no saved addresses yet.", "noOrders": "You have no orders yet.", - "order": "Order", - "orderDetailPlaceholder": "Order details will appear here once customer operations are connected.", + "olderOrders": "Older", "orders": "Orders", "ordersDescription": "View your order history", "profile": "Profile", "profileDescription": "Your account information", - "signOut": "Sign out" + "profileUpdated": "Profile updated", + "save": "Save", + "setAsDefault": "Set as default address", + "shipping": "Shipping", + "shippingAddress": "Shipping address", + "signOut": "Sign out", + "subtotal": "Subtotal", + "tax": "Tax", + "total": "Total", + "viewOrderStatus": "View order status" }, "agent": { "assistantLabel": "Shopping assistant", diff --git a/apps/template/lib/shopify/fetch.ts b/apps/template/lib/shopify/fetch.ts index b1611c20..4f1dc5f4 100644 --- a/apps/template/lib/shopify/fetch.ts +++ b/apps/template/lib/shopify/fetch.ts @@ -4,6 +4,7 @@ const SHOPIFY_API_VERSION = process.env.SHOPIFY_API_VERSION ?? "2026-04"; const DEBUG = process.env.DEBUG_SHOPIFY === "true"; const baseEndpoint = `https://${SHOPIFY_STORE_DOMAIN}/api/${SHOPIFY_API_VERSION}/graphql.json`; +const customerEndpoint = `https://${SHOPIFY_STORE_DOMAIN}/customer/api/${SHOPIFY_API_VERSION}/graphql`; export async function shopifyFetch({ operation, @@ -53,3 +54,54 @@ export async function shopifyFetch({ return json.data; } + +// Customer Account API is a separate GraphQL endpoint and schema from the +// Storefront API. It authenticates with the customer's OAuth access token sent +// as the raw `Authorization` header value (no `Bearer` prefix) and is always +// per-request (POST), so responses are never shared across customers. +export async function customerAccountFetch({ + accessToken, + operation, + query, + variables, +}: { + accessToken: string; + operation: string; + query: string; + variables?: Record; +}): Promise { + const endpoint = `${customerEndpoint}?operation=${operation}`; + const start = DEBUG ? performance.now() : 0; + + const response = await fetch(endpoint, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: accessToken, + "Accept-Encoding": "gzip, br", + }, + body: JSON.stringify({ query, variables, operationName: operation }), + }); + + if (!response.ok) { + throw new Error(`Shopify Customer API error: ${response.status} ${response.statusText}`); + } + + const json = await response.json(); + + if (DEBUG) { + const duration = performance.now() - start; + console.log(`[shopify:customer] ${operation} ${duration.toFixed(0)}ms`); + } + + if (json.errors) { + if (!json.data) { + throw new Error(`GraphQL errors: ${JSON.stringify(json.errors)}`); + } + console.warn( + `[shopify:customer] ${operation} returned partial errors: ${JSON.stringify(json.errors)}`, + ); + } + + return json.data; +} diff --git a/apps/template/lib/shopify/operations/customer.ts b/apps/template/lib/shopify/operations/customer.ts new file mode 100644 index 00000000..96b3daeb --- /dev/null +++ b/apps/template/lib/shopify/operations/customer.ts @@ -0,0 +1,353 @@ +import "server-only"; +import { requireSession } from "@/lib/auth/server"; +import type { + CustomerAddress, + CustomerAddressInput, + CustomerOrder, + CustomerOrdersPage, + CustomerProfile, +} from "@/lib/types"; + +import { customerAccountFetch } from "../fetch"; +import { + type ShopifyCustomerAddress, + type ShopifyCustomerProfile, + type ShopifyOrder, + type ShopifyOrderSummary, + transformCustomerAddress, + transformCustomerProfile, + transformOrder, + transformOrderSummary, +} from "../transforms/customer"; + +export const ORDERS_PER_PAGE = 10; + +export interface CustomerUserError { + code?: string; + field?: string[] | null; + message: string; +} + +const ADDRESS_FRAGMENT = ` + fragment AddressFields on CustomerAddress { + address1 + address2 + city + company + firstName + formatted + id + lastName + phoneNumber + territoryCode + zip + zoneCode + } +`; + +const ORDER_SUMMARY_FRAGMENT = ` + fragment OrderSummaryFields on Order { + financialStatus + fulfillmentStatus + id + name + number + processedAt + totalPrice { + amount + currencyCode + } + } +`; + +const GET_CUSTOMER_PROFILE_QUERY = ` + query getCustomerProfile { + customer { + emailAddress { + emailAddress + } + firstName + lastName + } + } +`; + +const GET_CUSTOMER_ORDERS_QUERY = ` + ${ORDER_SUMMARY_FRAGMENT} + query getCustomerOrders($after: String, $before: String, $first: Int, $last: Int) { + customer { + orders(after: $after, before: $before, first: $first, last: $last, reverse: true, sortKey: PROCESSED_AT) { + nodes { + ...OrderSummaryFields + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } + } +`; + +const GET_CUSTOMER_ORDER_QUERY = ` + ${ADDRESS_FRAGMENT} + ${ORDER_SUMMARY_FRAGMENT} + query getCustomerOrder($id: ID!) { + order(id: $id) { + ...OrderSummaryFields + lineItems(first: 50) { + nodes { + image { + altText + height + url + width + } + quantity + title + totalPrice { + amount + currencyCode + } + variantTitle + } + } + shippingAddress { + ...AddressFields + } + statusPageUrl + subtotal { + amount + currencyCode + } + totalShipping { + amount + currencyCode + } + totalTax { + amount + currencyCode + } + } + } +`; + +const GET_CUSTOMER_ADDRESSES_QUERY = ` + ${ADDRESS_FRAGMENT} + query getCustomerAddresses { + customer { + addresses(first: 30) { + nodes { + ...AddressFields + } + } + defaultAddress { + id + } + } + } +`; + +const CUSTOMER_ADDRESS_CREATE_MUTATION = ` + mutation customerAddressCreate($address: CustomerAddressInput!, $defaultAddress: Boolean) { + customerAddressCreate(address: $address, defaultAddress: $defaultAddress) { + customerAddress { + id + } + userErrors { + code + field + message + } + } + } +`; + +const CUSTOMER_ADDRESS_UPDATE_MUTATION = ` + mutation customerAddressUpdate($address: CustomerAddressInput, $addressId: ID!, $defaultAddress: Boolean) { + customerAddressUpdate(address: $address, addressId: $addressId, defaultAddress: $defaultAddress) { + customerAddress { + id + } + userErrors { + code + field + message + } + } + } +`; + +const CUSTOMER_ADDRESS_DELETE_MUTATION = ` + mutation customerAddressDelete($addressId: ID!) { + customerAddressDelete(addressId: $addressId) { + deletedAddressId + userErrors { + code + field + message + } + } + } +`; + +const CUSTOMER_UPDATE_MUTATION = ` + mutation customerUpdate($input: CustomerUpdateInput!) { + customerUpdate(input: $input) { + customer { + firstName + lastName + } + userErrors { + field + message + } + } + } +`; + +async function customerFetch( + operation: string, + query: string, + variables?: Record, +): Promise { + const { accessToken } = await requireSession(); + return customerAccountFetch({ accessToken, operation, query, variables }); +} + +export async function getCustomerProfile(): Promise { + const data = await customerFetch<{ customer: ShopifyCustomerProfile | null }>( + "getCustomerProfile", + GET_CUSTOMER_PROFILE_QUERY, + ); + + if (!data.customer) return null; + + return transformCustomerProfile(data.customer); +} + +export async function getCustomerOrders(cursor?: { + after?: string; + before?: string; +}): Promise { + const paginateBackward = Boolean(cursor?.before); + + const data = await customerFetch<{ + customer: { + orders: { + nodes: ShopifyOrderSummary[]; + pageInfo: { + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; + }; + }; + } | null; + }>("getCustomerOrders", GET_CUSTOMER_ORDERS_QUERY, { + after: cursor?.after, + before: cursor?.before, + first: paginateBackward ? undefined : ORDERS_PER_PAGE, + last: paginateBackward ? ORDERS_PER_PAGE : undefined, + }); + + const orders = data.customer?.orders; + if (!orders) { + return { + orders: [], + pageInfo: { + endCursor: null, + hasNextPage: false, + hasPreviousPage: false, + startCursor: null, + }, + }; + } + + return { + orders: orders.nodes.map(transformOrderSummary), + pageInfo: orders.pageInfo, + }; +} + +export async function getCustomerOrder(id: string): Promise { + const data = await customerFetch<{ order: ShopifyOrder | null }>( + "getCustomerOrder", + GET_CUSTOMER_ORDER_QUERY, + { id }, + ); + + if (!data.order) return null; + + return transformOrder(data.order); +} + +export async function getCustomerAddresses(): Promise { + const data = await customerFetch<{ + customer: { + addresses: { nodes: ShopifyCustomerAddress[] }; + defaultAddress: { id: string } | null; + } | null; + }>("getCustomerAddresses", GET_CUSTOMER_ADDRESSES_QUERY); + + if (!data.customer) return []; + + const defaultId = data.customer.defaultAddress?.id ?? null; + const addresses = data.customer.addresses.nodes.map((address) => + transformCustomerAddress(address, defaultId), + ); + + // Surface the default address first; it's the one customers act on most. + return addresses.sort((a, b) => Number(b.isDefault) - Number(a.isDefault)); +} + +export async function createCustomerAddress( + address: CustomerAddressInput, + defaultAddress: boolean, +): Promise { + const data = await customerFetch<{ + customerAddressCreate: { userErrors: CustomerUserError[] }; + }>("customerAddressCreate", CUSTOMER_ADDRESS_CREATE_MUTATION, { + address, + defaultAddress, + }); + + return data.customerAddressCreate.userErrors; +} + +export async function updateCustomerAddress( + addressId: string, + address: CustomerAddressInput, + defaultAddress: boolean, +): Promise { + const data = await customerFetch<{ + customerAddressUpdate: { userErrors: CustomerUserError[] }; + }>("customerAddressUpdate", CUSTOMER_ADDRESS_UPDATE_MUTATION, { + address, + addressId, + defaultAddress, + }); + + return data.customerAddressUpdate.userErrors; +} + +export async function deleteCustomerAddress(addressId: string): Promise { + const data = await customerFetch<{ + customerAddressDelete: { userErrors: CustomerUserError[] }; + }>("customerAddressDelete", CUSTOMER_ADDRESS_DELETE_MUTATION, { addressId }); + + return data.customerAddressDelete.userErrors; +} + +export async function updateCustomerProfile(input: { + firstName: string; + lastName: string; +}): Promise { + const data = await customerFetch<{ + customerUpdate: { userErrors: CustomerUserError[] }; + }>("customerUpdate", CUSTOMER_UPDATE_MUTATION, { input }); + + return data.customerUpdate.userErrors; +} diff --git a/apps/template/lib/shopify/transforms/customer.ts b/apps/template/lib/shopify/transforms/customer.ts new file mode 100644 index 00000000..c4d0e25d --- /dev/null +++ b/apps/template/lib/shopify/transforms/customer.ts @@ -0,0 +1,146 @@ +import type { + CustomerAddress, + CustomerOrder, + CustomerOrderSummary, + CustomerProfile, + Image, + Money, + OrderLineItem, +} from "@/lib/types"; + +interface ShopifyMoney { + amount: string; + currencyCode: string; +} + +interface ShopifyImage { + altText: string | null; + height: number | null; + url: string; + width: number | null; +} + +export interface ShopifyCustomerAddress { + address1: string | null; + address2: string | null; + city: string | null; + company: string | null; + firstName: string | null; + formatted: string[]; + id: string; + lastName: string | null; + phoneNumber: string | null; + territoryCode: string | null; + zip: string | null; + zoneCode: string | null; +} + +interface ShopifyLineItem { + image: ShopifyImage | null; + quantity: number; + title: string; + totalPrice: ShopifyMoney | null; + variantTitle: string | null; +} + +export interface ShopifyOrderSummary { + financialStatus: string | null; + fulfillmentStatus: string; + id: string; + name: string; + number: number; + processedAt: string; + totalPrice: ShopifyMoney; +} + +export interface ShopifyOrder extends ShopifyOrderSummary { + lineItems: { nodes: ShopifyLineItem[] }; + shippingAddress: ShopifyCustomerAddress | null; + statusPageUrl: string; + subtotal: ShopifyMoney | null; + totalShipping: ShopifyMoney | null; + totalTax: ShopifyMoney | null; +} + +export interface ShopifyCustomerProfile { + emailAddress: { emailAddress: string } | null; + firstName: string | null; + lastName: string | null; +} + +function transformMoney(money: ShopifyMoney): Money { + return { amount: money.amount, currencyCode: money.currencyCode }; +} + +function transformImage(image: ShopifyImage | null): Image | null { + if (!image) return null; + return { + altText: image.altText ?? "", + height: image.height ?? 0, + url: image.url, + width: image.width ?? 0, + }; +} + +export function transformCustomerAddress( + address: ShopifyCustomerAddress, + defaultAddressId?: string | null, +): CustomerAddress { + return { + address1: address.address1, + address2: address.address2, + city: address.city, + company: address.company, + firstName: address.firstName, + formatted: address.formatted, + id: address.id, + isDefault: defaultAddressId != null && address.id === defaultAddressId, + lastName: address.lastName, + phoneNumber: address.phoneNumber, + territoryCode: address.territoryCode, + zip: address.zip, + zoneCode: address.zoneCode, + }; +} + +export function transformOrderSummary(order: ShopifyOrderSummary): CustomerOrderSummary { + return { + financialStatus: order.financialStatus, + fulfillmentStatus: order.fulfillmentStatus, + id: order.id, + name: order.name, + number: order.number, + processedAt: order.processedAt, + totalPrice: transformMoney(order.totalPrice), + }; +} + +function transformLineItem(item: ShopifyLineItem): OrderLineItem { + return { + image: transformImage(item.image), + quantity: item.quantity, + title: item.title, + totalPrice: item.totalPrice ? transformMoney(item.totalPrice) : null, + variantTitle: item.variantTitle, + }; +} + +export function transformOrder(order: ShopifyOrder): CustomerOrder { + return { + ...transformOrderSummary(order), + lineItems: order.lineItems.nodes.map(transformLineItem), + shippingAddress: order.shippingAddress ? transformCustomerAddress(order.shippingAddress) : null, + statusPageUrl: order.statusPageUrl, + subtotal: order.subtotal ? transformMoney(order.subtotal) : null, + totalShipping: order.totalShipping ? transformMoney(order.totalShipping) : null, + totalTax: order.totalTax ? transformMoney(order.totalTax) : null, + }; +} + +export function transformCustomerProfile(customer: ShopifyCustomerProfile): CustomerProfile { + return { + email: customer.emailAddress?.emailAddress ?? "", + firstName: customer.firstName, + lastName: customer.lastName, + }; +} diff --git a/apps/template/lib/types.ts b/apps/template/lib/types.ts index 330aa8a0..061d5275 100644 --- a/apps/template/lib/types.ts +++ b/apps/template/lib/types.ts @@ -290,3 +290,74 @@ export interface BannerSection { id: string; subheadline: string | null; } + +// Customer account — populated from the Shopify Customer Account API (a separate +// schema from the Storefront API). Status fields hold raw Shopify enum values +// (e.g. "FULFILLED", "PAID"); humanize them at the display layer. + +export interface CustomerProfile { + email: string; + firstName: string | null; + lastName: string | null; +} + +export interface OrderLineItem { + image: Image | null; + quantity: number; + title: string; + totalPrice: Money | null; + variantTitle: string | null; +} + +export interface CustomerOrderSummary { + financialStatus: string | null; + fulfillmentStatus: string; + id: string; + name: string; + number: number; + processedAt: string; + totalPrice: Money; +} + +export interface CustomerOrder extends CustomerOrderSummary { + lineItems: OrderLineItem[]; + shippingAddress: CustomerAddress | null; + statusPageUrl: string; + subtotal: Money | null; + totalShipping: Money | null; + totalTax: Money | null; +} + +export interface CustomerOrdersPage { + orders: CustomerOrderSummary[]; + pageInfo: PageInfo; +} + +export interface CustomerAddress { + address1: string | null; + address2: string | null; + city: string | null; + company: string | null; + firstName: string | null; + formatted: string[]; + id: string; + isDefault: boolean; + lastName: string | null; + phoneNumber: string | null; + territoryCode: string | null; + zip: string | null; + zoneCode: string | null; +} + +export interface CustomerAddressInput { + address1?: string; + address2?: string; + city?: string; + company?: string; + firstName?: string; + lastName?: string; + phoneNumber?: string; + territoryCode?: string; + zip?: string; + zoneCode?: string; +} diff --git a/packages/plugin/template-rollout-log/2026-06-07-customer-account-api-operations.md b/packages/plugin/template-rollout-log/2026-06-07-customer-account-api-operations.md new file mode 100644 index 00000000..77e5f83d --- /dev/null +++ b/packages/plugin/template-rollout-log/2026-06-07-customer-account-api-operations.md @@ -0,0 +1,72 @@ +--- +title: Customer Account API operations — live orders, order detail, address CRUD, profile editing +changeKey: customer-account-api-operations +introducedOn: 2026-06-07 +changeType: feat +defaultAction: adopt +appliesTo: + - all +paths: + - apps/template/app/account/(authenticated)/addresses/page.tsx + - apps/template/app/account/(authenticated)/orders/[id]/page.tsx + - apps/template/app/account/(authenticated)/orders/page.tsx + - apps/template/app/account/(authenticated)/profile/page.tsx + - apps/template/components/account/address-book.tsx + - apps/template/components/account/order-display.tsx + - apps/template/components/account/profile-form.tsx + - apps/template/lib/customer/action.ts + - apps/template/lib/shopify/fetch.ts + - apps/template/lib/shopify/operations/customer.ts + - apps/template/lib/shopify/transforms/customer.ts + - apps/template/lib/types.ts + - apps/template/lib/i18n/messages/en.json + - apps/docs/content/docs/anatomy/authentication.mdx +--- + +## Summary + +The account pages were scaffolds — `/account/orders`, `/account/orders/[id]`, and `/account/addresses` rendered empty-state placeholders, and `/account/profile` showed read-only session data. This change wires them to the Shopify Customer Account API so they match what Hydrogen ships: + +- **Orders** — cursor-paginated history (newest first), each row linking to detail. +- **Order detail** — line items with thumbnails, order/financial status, totals (subtotal, shipping, tax, total), shipping address, and a link to Shopify's hosted status page. +- **Addresses** — full CRUD with create, edit, delete, and default-address selection. +- **Profile** — editable first/last name (email shown read-only) via `customerUpdate`. + +The data layer is new and mirrors the existing Storefront layer: + +- `lib/shopify/fetch.ts` gains `customerAccountFetch()`, which POSTs to `https://{domain}/customer/api/{version}/graphql` with the customer's OAuth access token as the raw `Authorization` header (no `Bearer` prefix) — a separate endpoint and schema from the Storefront API. +- `lib/shopify/operations/customer.ts` holds the queries and mutations; each resolves the access token through `requireSession()`. +- `lib/shopify/transforms/customer.ts` maps responses to provider-agnostic types in `lib/types.ts`. +- `lib/customer/action.ts` provides `"use server"` actions for the address and profile forms (validation, `userErrors` surfacing, `revalidatePath`). + +All GraphQL was validated against the live `2026-04` Customer Account API schema. + +## Why it matters + +- Closes the largest gap from the Hydrogen comparison: the account area is now functional, not stubbed. +- Establishes the Customer Account API fetch/operation/transform/action pattern downstream storefronts can extend (store credit, subscriptions, draft orders) without re-deriving the endpoint and auth-header quirks. +- Keeps token handling server-only and per-request — order data is never shared across customers. + +## Apply when + +- The storefront uses the built-in better-auth + Shopify OIDC auth (`NEXT_PUBLIC_ENABLE_AUTH="1"`) largely as shipped. +- The account pages are still the template's scaffolds (no custom order/address UI already wired). + +## Safe to skip when + +- The storefront has replaced the account area with its own implementation or a different identity provider. +- The storefront intentionally keeps a guest-only experience with auth disabled. + +## Notes + +- Country (`territoryCode`) and region (`zoneCode`) are collected as ISO-code text inputs. A country/region dropdown is a reasonable enhancement layered on top — `CustomerAddressInput` is unchanged. +- Status enums (`fulfillmentStatus`, `financialStatus`) are humanized at the display layer, not stored in locale catalogs. +- The nav/sidebar name still comes from the better-auth session (ID token), so a profile name edit isn't reflected there until the next sign-in; the profile page itself shows the updated value immediately. + +## Validation + +1. `pnpm --filter template build` with auth configured — account pages compile and render. +2. Sign in, visit `/account/orders` — orders list newest-first; "Older"/"Newer" paginate. +3. Open an order — line items, totals, shipping address, and "View order status" link render. +4. `/account/addresses` — add, edit, delete an address; toggle default; confirm changes persist after reload. +5. `/account/profile` — edit first/last name, save, confirm the value persists after reload. From fbb4ffcf3cb6aab591c0b8c127c59ba08fe67889 Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 16:14:54 -0500 Subject: [PATCH 08/13] [template] account: resolve Customer Account API endpoint from OIDC discovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Customer Account API GraphQL endpoint is not served on the storefront domain — that path 302s to an HTML page, so response.json() threw "Unexpected token '<'". Derive the real endpoint (https://shopify.com/{shopId}/account/customer/api/{version}/graphql) from the shop ID in the OIDC issuer, cache it, and surface non-JSON responses with a legible error. Co-Authored-By: Claude Opus 4.7 --- .../content/docs/anatomy/authentication.mdx | 2 +- apps/template/lib/shopify/fetch.ts | 50 +++++++++++++++++-- ...6-06-07-customer-account-api-operations.md | 2 +- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/apps/docs/content/docs/anatomy/authentication.mdx b/apps/docs/content/docs/anatomy/authentication.mdx index e0cff093..e4577e3d 100644 --- a/apps/docs/content/docs/anatomy/authentication.mdx +++ b/apps/docs/content/docs/anatomy/authentication.mdx @@ -126,7 +126,7 @@ The account pages read and write customer data through the Shopify Customer Acco | Module | Purpose | | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| `lib/shopify/fetch.ts` | `customerAccountFetch()` — POSTs to `https://{domain}/customer/api/{version}/graphql` with the customer's access token as the raw `Authorization` header (no `Bearer` prefix). | +| `lib/shopify/fetch.ts` | `customerAccountFetch()` — POSTs to `https://shopify.com/{shopId}/account/customer/api/{version}/graphql` (the `shopId` is derived from the OIDC discovery document's `issuer` and cached) with the customer's access token as the raw `Authorization` header (no `Bearer` prefix). The endpoint is **not** on the storefront domain. | | `lib/shopify/operations/customer.ts` | Queries (profile, orders, order detail, addresses) and mutations (address create/update/delete, profile update). Each call resolves the token via `requireSession()`. | | `lib/shopify/transforms/customer.ts` | Maps Customer Account API responses to the provider-agnostic domain types in `lib/types.ts`. | | `lib/customer/action.ts` | `"use server"` actions for the address and profile forms. They validate input, surface Shopify `userErrors`, and `revalidatePath` on success. | diff --git a/apps/template/lib/shopify/fetch.ts b/apps/template/lib/shopify/fetch.ts index 4f1dc5f4..b2d273f1 100644 --- a/apps/template/lib/shopify/fetch.ts +++ b/apps/template/lib/shopify/fetch.ts @@ -4,7 +4,6 @@ const SHOPIFY_API_VERSION = process.env.SHOPIFY_API_VERSION ?? "2026-04"; const DEBUG = process.env.DEBUG_SHOPIFY === "true"; const baseEndpoint = `https://${SHOPIFY_STORE_DOMAIN}/api/${SHOPIFY_API_VERSION}/graphql.json`; -const customerEndpoint = `https://${SHOPIFY_STORE_DOMAIN}/customer/api/${SHOPIFY_API_VERSION}/graphql`; export async function shopifyFetch({ operation, @@ -55,6 +54,38 @@ export async function shopifyFetch({ return json.data; } +// The Customer Account API GraphQL endpoint is NOT served on the storefront +// domain (that path 302s to an HTML page). It lives at +// https://shopify.com/{shopId}/account/customer/api/{version}/graphql, where +// {shopId} is the numeric ID embedded in the OIDC issuer. Derive it from the +// store's discovery document — cached for the process lifetime — so the +// template needs no configuration beyond SHOPIFY_STORE_DOMAIN. +let customerApiEndpointPromise: Promise | undefined; + +function resolveCustomerApiEndpoint(): Promise { + if (!customerApiEndpointPromise) { + customerApiEndpointPromise = (async () => { + const response = await fetch( + `https://${SHOPIFY_STORE_DOMAIN}/.well-known/openid-configuration`, + { next: { revalidate: 86400 } }, + ); + if (!response.ok) { + throw new Error(`Failed to load Shopify OIDC discovery: ${response.status}`); + } + const config: { issuer?: string } = await response.json(); + const shopId = config.issuer?.split("/").pop(); + if (!shopId) { + throw new Error("Could not derive Shopify shop ID from OIDC issuer"); + } + return `https://shopify.com/${shopId}/account/customer/api/${SHOPIFY_API_VERSION}/graphql`; + })().catch((error) => { + customerApiEndpointPromise = undefined; + throw error; + }); + } + return customerApiEndpointPromise; +} + // Customer Account API is a separate GraphQL endpoint and schema from the // Storefront API. It authenticates with the customer's OAuth access token sent // as the raw `Authorization` header value (no `Bearer` prefix) and is always @@ -70,7 +101,8 @@ export async function customerAccountFetch({ query: string; variables?: Record; }): Promise { - const endpoint = `${customerEndpoint}?operation=${operation}`; + const baseUrl = await resolveCustomerApiEndpoint(); + const endpoint = `${baseUrl}?operation=${operation}`; const start = DEBUG ? performance.now() : 0; const response = await fetch(endpoint, { @@ -87,7 +119,17 @@ export async function customerAccountFetch({ throw new Error(`Shopify Customer API error: ${response.status} ${response.statusText}`); } - const json = await response.json(); + // Guard against a non-JSON body (e.g. an HTML redirect from a misrouted + // endpoint) so the failure is legible instead of a bare JSON.parse error. + const text = await response.text(); + let json: { data?: T; errors?: unknown }; + try { + json = JSON.parse(text); + } catch { + throw new Error( + `Shopify Customer API returned non-JSON (status ${response.status}): ${text.slice(0, 120)}`, + ); + } if (DEBUG) { const duration = performance.now() - start; @@ -103,5 +145,5 @@ export async function customerAccountFetch({ ); } - return json.data; + return json.data as T; } diff --git a/packages/plugin/template-rollout-log/2026-06-07-customer-account-api-operations.md b/packages/plugin/template-rollout-log/2026-06-07-customer-account-api-operations.md index 77e5f83d..8a4f3864 100644 --- a/packages/plugin/template-rollout-log/2026-06-07-customer-account-api-operations.md +++ b/packages/plugin/template-rollout-log/2026-06-07-customer-account-api-operations.md @@ -34,7 +34,7 @@ The account pages were scaffolds — `/account/orders`, `/account/orders/[id]`, The data layer is new and mirrors the existing Storefront layer: -- `lib/shopify/fetch.ts` gains `customerAccountFetch()`, which POSTs to `https://{domain}/customer/api/{version}/graphql` with the customer's OAuth access token as the raw `Authorization` header (no `Bearer` prefix) — a separate endpoint and schema from the Storefront API. +- `lib/shopify/fetch.ts` gains `customerAccountFetch()`, which POSTs to the Customer Account API GraphQL endpoint with the customer's OAuth access token as the raw `Authorization` header (no `Bearer` prefix) — a separate endpoint and schema from the Storefront API. The endpoint is `https://shopify.com/{shopId}/account/customer/api/{version}/graphql`; the `shopId` is derived from the OIDC discovery document's `issuer` (the storefront-domain path 302s to HTML and must not be used) and cached for the process lifetime. - `lib/shopify/operations/customer.ts` holds the queries and mutations; each resolves the access token through `requireSession()`. - `lib/shopify/transforms/customer.ts` maps responses to provider-agnostic types in `lib/types.ts`. - `lib/customer/action.ts` provides `"use server"` actions for the address and profile forms (validation, `userErrors` surfacing, `revalidatePath`). From 1254474f119cadecd0d616c6a184ce454718b187 Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 16:45:30 -0500 Subject: [PATCH 09/13] [docs] auth: fix Markdown table padding in auth and env-vars docs Co-Authored-By: Claude Opus 4.7 --- apps/docs/content/docs/anatomy/authentication.mdx | 14 +++++++------- apps/docs/content/docs/reference/env-vars.mdx | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/docs/content/docs/anatomy/authentication.mdx b/apps/docs/content/docs/anatomy/authentication.mdx index e4577e3d..414e02f3 100644 --- a/apps/docs/content/docs/anatomy/authentication.mdx +++ b/apps/docs/content/docs/anatomy/authentication.mdx @@ -67,7 +67,7 @@ Authentication uses Shopify-native URL paths: | `/account/profile` | View and edit the customer's name; email shown read-only. | | `/account/orders` | Paginated order history (cursor-based, newest first). | | `/account/orders/[id]` | Order detail: line items, totals, shipping address, and a status-page link. | -| `/account/addresses` | Address book with create, edit, delete, and default selection. | +| `/account/addresses` | Address book with create, edit, delete, and default selection. | The account pages use a `(authenticated)` route group so the auth-gated layout applies to protected pages without blocking `/account/login`. @@ -124,12 +124,12 @@ function AccountMenu() { The account pages read and write customer data through the Shopify Customer Account API — a separate GraphQL endpoint and schema from the Storefront API. -| Module | Purpose | -| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| `lib/shopify/fetch.ts` | `customerAccountFetch()` — POSTs to `https://shopify.com/{shopId}/account/customer/api/{version}/graphql` (the `shopId` is derived from the OIDC discovery document's `issuer` and cached) with the customer's access token as the raw `Authorization` header (no `Bearer` prefix). The endpoint is **not** on the storefront domain. | -| `lib/shopify/operations/customer.ts` | Queries (profile, orders, order detail, addresses) and mutations (address create/update/delete, profile update). Each call resolves the token via `requireSession()`. | -| `lib/shopify/transforms/customer.ts` | Maps Customer Account API responses to the provider-agnostic domain types in `lib/types.ts`. | -| `lib/customer/action.ts` | `"use server"` actions for the address and profile forms. They validate input, surface Shopify `userErrors`, and `revalidatePath` on success. | +| Module | Purpose | +| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `lib/shopify/fetch.ts` | `customerAccountFetch()` — POSTs to `https://shopify.com/{shopId}/account/customer/api/{version}/graphql` (the `shopId` is derived from the OIDC discovery document's `issuer` and cached) with the customer's access token as the raw `Authorization` header (no `Bearer` prefix). The endpoint is **not** on the storefront domain. | +| `lib/shopify/operations/customer.ts` | Queries (profile, orders, order detail, addresses) and mutations (address create/update/delete, profile update). Each call resolves the token via `requireSession()`. | +| `lib/shopify/transforms/customer.ts` | Maps Customer Account API responses to the provider-agnostic domain types in `lib/types.ts`. | +| `lib/customer/action.ts` | `"use server"` actions for the address and profile forms. They validate input, surface Shopify `userErrors`, and `revalidatePath` on success. | Order and profile pages are read-only server components wrapped in Suspense. Addresses and profile editing use client forms that call the server actions. Order requests are per-customer `POST`s, so responses are never shared across customers. diff --git a/apps/docs/content/docs/reference/env-vars.mdx b/apps/docs/content/docs/reference/env-vars.mdx index da92cde8..c04cfd2b 100644 --- a/apps/docs/content/docs/reference/env-vars.mdx +++ b/apps/docs/content/docs/reference/env-vars.mdx @@ -25,11 +25,11 @@ Both optional features are opt-in via explicit `NEXT_PUBLIC_ENABLE_*` flags. The Required when `NEXT_PUBLIC_ENABLE_AUTH="1"`. Powers built-in customer authentication via [better-auth](https://www.better-auth.com/) and Shopify Customer Account API OIDC. -| Variable | Description | -| -------------------------------- | -------------------------------------------------------------------------------------------------------- | -| `BETTER_AUTH_SECRET` | Secret for signing sessions. Generate with `openssl rand -base64 32`. | -| `SHOPIFY_CUSTOMER_CLIENT_ID` | Customer Account API client ID. Found in **Sales channels → Headless → Customer Account API**. | -| `SHOPIFY_CUSTOMER_CLIENT_SECRET` | Customer Account API client secret. Same location as the client ID; requires a **Confidential** client. | +| Variable | Description | +| -------------------------------- | ------------------------------------------------------------------------------------------------------- | +| `BETTER_AUTH_SECRET` | Secret for signing sessions. Generate with `openssl rand -base64 32`. | +| `SHOPIFY_CUSTOMER_CLIENT_ID` | Customer Account API client ID. Found in **Sales channels → Headless → Customer Account API**. | +| `SHOPIFY_CUSTOMER_CLIENT_SECRET` | Customer Account API client secret. Same location as the client ID; requires a **Confidential** client. | ## Optional From bb50a8cd3ac0f57db9a077561b21a00f1f56b807 Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 16:45:36 -0500 Subject: [PATCH 10/13] lint: exclude vendored ai-elements from oxlint The components/ai-elements directory is vendored shadcn-style code; its upstream exhaustive-deps warning is not ours to own. Ignore it in both the template and docs oxlint configs. Co-Authored-By: Claude Opus 4.7 --- apps/docs/.oxlintrc.json | 2 +- apps/template/.oxlintrc.json | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/docs/.oxlintrc.json b/apps/docs/.oxlintrc.json index 9cfc4975..11064326 100644 --- a/apps/docs/.oxlintrc.json +++ b/apps/docs/.oxlintrc.json @@ -4,7 +4,7 @@ "correctness": "warn", "suspicious": "warn" }, - "ignorePatterns": [".next/**", "dist/**", "build/**", ".claude/**"], + "ignorePatterns": [".next/**", "dist/**", "build/**", ".claude/**", "components/ai-elements/**"], "plugins": ["typescript", "react", "nextjs"], "rules": { "no-underscore-dangle": ["warn", { "allow": ["__dirname", "__registerFileInput"] }], diff --git a/apps/template/.oxlintrc.json b/apps/template/.oxlintrc.json index d36a0e6a..261961ab 100644 --- a/apps/template/.oxlintrc.json +++ b/apps/template/.oxlintrc.json @@ -4,7 +4,14 @@ "correctness": "warn", "suspicious": "warn" }, - "ignorePatterns": [".next/**", "dist/**", "build/**", ".claude/**", "app/.well-known/**"], + "ignorePatterns": [ + ".next/**", + "dist/**", + "build/**", + ".claude/**", + "app/.well-known/**", + "components/ai-elements/**" + ], "plugins": ["typescript", "react", "nextjs"], "rules": { "no-underscore-dangle": ["warn", { "allow": ["__typename"] }], From 8a1d366b78bc20260775218edf52993d455d7b50 Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 19:21:43 -0500 Subject: [PATCH 11/13] [template] pdp: fetch up to 250 product variants instead of 50 50 silently truncated products with large variant matrices, leaving some variants unselectable. Raise PRODUCT_FRAGMENT to the Storefront API's 250 max. Updates the PDP and storefront-api docs and adds a rollout-log entry for downstream adoption. Co-Authored-By: Claude Opus 4.7 --- .../content/docs/reference/storefront-api.mdx | 14 +++---- apps/docs/content/docs/shopify/pdp.mdx | 2 +- apps/template/lib/shopify/fragments.ts | 2 +- .../2026-06-07-pdp-variants-first-250.md | 37 +++++++++++++++++++ 4 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 packages/plugin/template-rollout-log/2026-06-07-pdp-variants-first-250.md diff --git a/apps/docs/content/docs/reference/storefront-api.mdx b/apps/docs/content/docs/reference/storefront-api.mdx index e5b16cf7..206b3365 100644 --- a/apps/docs/content/docs/reference/storefront-api.mdx +++ b/apps/docs/content/docs/reference/storefront-api.mdx @@ -70,13 +70,13 @@ Always verify fields against the live Storefront API schema with `shopify-ai-too Shared fragments in `lib/shopify/fragments.ts` avoid repeating field selections: -| Fragment | Covers | -| --------------------------- | ---------------------------------------------------------------------------------------------- | -| `MONEY_FRAGMENT` | `amount` and `currencyCode` on `MoneyV2` | -| `IMAGE_FRAGMENT` | `url`, `altText`, `width`, `height` on `Image` | -| `PRODUCT_VARIANT_FRAGMENT` | Variant price, options, image, availability | -| `PRODUCT_FRAGMENT` | Full product: media, variants (up to 50), options with swatches, metafields, price ranges, SEO | -| `CATEGORY_PRODUCT_FRAGMENT` | Lightweight product for listing pages (fewer fields) | +| Fragment | Covers | +| --------------------------- | ----------------------------------------------------------------------------------------------- | +| `MONEY_FRAGMENT` | `amount` and `currencyCode` on `MoneyV2` | +| `IMAGE_FRAGMENT` | `url`, `altText`, `width`, `height` on `Image` | +| `PRODUCT_VARIANT_FRAGMENT` | Variant price, options, image, availability | +| `PRODUCT_FRAGMENT` | Full product: media, variants (up to 250), options with swatches, metafields, price ranges, SEO | +| `CATEGORY_PRODUCT_FRAGMENT` | Lightweight product for listing pages (fewer fields) | Embed fragments in a query with template literal interpolation: `` `${PRODUCT_FRAGMENT} query ...` ``. diff --git a/apps/docs/content/docs/shopify/pdp.mdx b/apps/docs/content/docs/shopify/pdp.mdx index 8e48a05f..8a157567 100644 --- a/apps/docs/content/docs/shopify/pdp.mdx +++ b/apps/docs/content/docs/shopify/pdp.mdx @@ -16,7 +16,7 @@ The PDP renders any product that has a handle (URL slug) in Shopify. At minimum, - At least one **variant** (even single-option products have a default variant) - A **featured image** and optionally up to 10 media items (images or videos) -The template fetches up to 50 variants per product and 10 media items. +The template fetches up to 250 variants per product and 10 media items. ## Metafields diff --git a/apps/template/lib/shopify/fragments.ts b/apps/template/lib/shopify/fragments.ts index 4ab67e45..1a83a796 100644 --- a/apps/template/lib/shopify/fragments.ts +++ b/apps/template/lib/shopify/fragments.ts @@ -243,7 +243,7 @@ export const PRODUCT_FRAGMENT = ` ...MoneyFields } } - variants(first: 50) { + variants(first: 250) { edges { node { ...ProductVariantFields diff --git a/packages/plugin/template-rollout-log/2026-06-07-pdp-variants-first-250.md b/packages/plugin/template-rollout-log/2026-06-07-pdp-variants-first-250.md new file mode 100644 index 00000000..4f7232e1 --- /dev/null +++ b/packages/plugin/template-rollout-log/2026-06-07-pdp-variants-first-250.md @@ -0,0 +1,37 @@ +--- +title: PDP — fetch up to 250 product variants instead of 50 +changeKey: pdp-variants-first-250 +introducedOn: 2026-06-07 +changeType: enhancement +defaultAction: adopt +appliesTo: + - all +paths: + - apps/template/lib/shopify/fragments.ts +--- + +## Summary + +`PRODUCT_FRAGMENT` selected `variants(first: 50)`. Products with more than 50 variants (large size/color matrices, configurable products) had their extra variants silently dropped from the PDP — those options couldn't be selected or purchased. + +Bumped the limit to `variants(first: 250)`, which is the Storefront API's maximum page size for a connection. + +## Why it matters + +50 is below what a real catalog can carry: a product with, say, 8 sizes × 7 colors already exceeds it. The truncation is invisible — the query succeeds, the page renders, and only the missing variants reveal the problem. Downstream storefronts with deep variant matrices would otherwise hit this as a hard-to-spot "some variants can't be bought" bug. + +## Apply when + +- The storefront uses `PRODUCT_FRAGMENT` from `lib/shopify/fragments.ts` largely as shipped. +- Any product could plausibly carry more than 50 variants. + +## Safe to skip when + +- Every product is known to stay under 50 variants and the smaller response payload is worth keeping. +- The storefront has already moved variant fetching to a paginated/lazy approach. + +## Validation + +1. `pnpm --filter template dev`. +2. Visit a PDP for a product with more than 50 variants and confirm every variant combination is selectable and purchasable. +3. Confirm normal multi- and single-variant PDPs are unaffected. From d09238c47310ff1df73eb92fa0153ef022ccff4f Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Sun, 7 Jun 2026 19:59:38 -0500 Subject: [PATCH 12/13] [template] sitemap: paged shards matching Hydrogen's model (#311) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sitemap index + paged children backed by Shopify's Storefront sitemap(type:) query — the model Hydrogen uses. Each child holds ≤250 entries. - New URLs: /sitemap.xml (index) + /sitemap/{static,products-{n},collections-{n}}.xml (children) - Implemented as route handlers to avoid colliding with Next.js's reserved /sitemap.xml metadata route - Adds a Sitemap anatomy docs page --- apps/docs/content/docs/anatomy/_meta.json | 1 + apps/docs/content/docs/anatomy/aeo-geo.mdx | 14 +-- apps/docs/content/docs/anatomy/sitemap.mdx | 41 +++++++++ apps/docs/content/docs/skills/enable-i18n.mdx | 15 ++-- .../docs/skills/enable-shopify-cms.mdx | 2 +- .../docs/skills/enable-shopify-markets.mdx | 15 ++-- apps/template/app/sitemap.ts | 31 ------- apps/template/app/sitemap.xml/route.ts | 35 ++++++++ apps/template/app/sitemap/[shard]/route.ts | 67 ++++++++++++++ .../lib/shopify/operations/sitemap.ts | 89 ++++++++++--------- packages/plugin/skills/enable-i18n/SKILL.md | 15 ++-- .../plugin/skills/enable-shopify-cms/SKILL.md | 2 +- .../skills/enable-shopify-markets/SKILL.md | 15 ++-- .../2026-06-04-hydrogen-parity-sitemap.md | 59 ++++++++++++ 14 files changed, 297 insertions(+), 104 deletions(-) create mode 100644 apps/docs/content/docs/anatomy/sitemap.mdx delete mode 100644 apps/template/app/sitemap.ts create mode 100644 apps/template/app/sitemap.xml/route.ts create mode 100644 apps/template/app/sitemap/[shard]/route.ts create mode 100644 packages/plugin/template-rollout-log/2026-06-04-hydrogen-parity-sitemap.md diff --git a/apps/docs/content/docs/anatomy/_meta.json b/apps/docs/content/docs/anatomy/_meta.json index a5eb82d1..f245ffa1 100644 --- a/apps/docs/content/docs/anatomy/_meta.json +++ b/apps/docs/content/docs/anatomy/_meta.json @@ -9,6 +9,7 @@ "navigation", "footer", "aeo-geo", + "sitemap", "webhooks" ] } diff --git a/apps/docs/content/docs/anatomy/aeo-geo.mdx b/apps/docs/content/docs/anatomy/aeo-geo.mdx index 7a02fdfe..d89caeb3 100644 --- a/apps/docs/content/docs/anatomy/aeo-geo.mdx +++ b/apps/docs/content/docs/anatomy/aeo-geo.mdx @@ -12,13 +12,13 @@ The template ships with several built-in surfaces that contribute to AEO/GEO. Th ## Surfaces in the template -| Surface | What it does | Key files | -| -------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------- | -| **Content negotiation** | Serves clean markdown to AI clients via `Accept: text/markdown` | `next.config.ts`, `app/md/**`, `lib/markdown/**` | -| **Schema.org JSON-LD** | Embeds structured `Product`, `BreadcrumbList`, and `Organization` data | `components/product-detail/schema.tsx`, `components/schema/**` | -| **Sitemap** | Enumerates products, collections, and pages for crawlers | `app/sitemap.ts`, `lib/shopify/operations/sitemap.ts` | -| **Robots** | Declares crawl policy and blocks faceted (sort/filter) collection URLs | `app/robots.ts` | -| **OpenGraph & Twitter metadata** | Provides title, description, and image previews per route | `lib/seo.ts`, route-level `generateMetadata` | +| Surface | What it does | Key files | +| -------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------- | +| **Content negotiation** | Serves clean markdown to AI clients via `Accept: text/markdown` | `next.config.ts`, `app/md/**`, `lib/markdown/**` | +| **Schema.org JSON-LD** | Embeds structured `Product`, `BreadcrumbList`, and `Organization` data | `components/product-detail/schema.tsx`, `components/schema/**` | +| **Sitemap** | [Sitemap index + paged children](/docs/anatomy/sitemap) for products and collections | `app/sitemap.xml/route.ts`, `app/sitemap/[shard]/route.ts` | +| **Robots** | Declares crawl policy and blocks faceted (sort/filter) collection URLs | `app/robots.ts` | +| **OpenGraph & Twitter metadata** | Provides title, description, and image previews per route | `lib/seo.ts`, route-level `generateMetadata` | The rest of this page goes deep on content negotiation. The other surfaces are documented inline in the linked files. diff --git a/apps/docs/content/docs/anatomy/sitemap.mdx b/apps/docs/content/docs/anatomy/sitemap.mdx new file mode 100644 index 00000000..4a785cf9 --- /dev/null +++ b/apps/docs/content/docs/anatomy/sitemap.mdx @@ -0,0 +1,41 @@ +--- +title: Sitemap +description: A sitemap index plus paged child sitemaps backed by Shopify's Storefront sitemap query — the same model Hydrogen uses. +type: guide +--- + +The storefront exposes a sitemap index at `/sitemap.xml` and paged children at `/sitemap/{shard}.xml`. Each child holds up to 250 entries — Shopify's Storefront `sitemap(type:)` query computes the pagination, so the storefront just iterates. + +`robots.ts` points crawlers at `/sitemap.xml`; that URL alone is enough to discover every product and collection. + +## URLs + +| URL | Contents | +| ------------------------------ | --------------------------------------- | +| `/sitemap.xml` | Sitemap index listing every child shard | +| `/sitemap/static.xml` | Home page | +| `/sitemap/products-{n}.xml` | Up to 250 products per shard | +| `/sitemap/collections-{n}.xml` | Up to 250 collections per shard | + +`{n}` is 1-indexed and runs to the `pagesCount` Shopify returns for each type. + +## Cache behavior + +Both the page count and each page of resources are cached with `cacheLife("max")` and tagged `products` or `collections`. The webhook handler at [`/api/webhooks/shopify`](/docs/anatomy/webhooks) invalidates those tags on product/collection mutation, so the sitemap stays fresh without scheduled regeneration. + +## Adding more resource types + +The template scopes sitemaps to products and collections. Shopify's `SitemapType` enum also covers `PAGE`, `BLOG`, `ARTICLE`, and `METAOBJECT`. Both routes name those two types explicitly, so adding one touches three places: + +1. **`lib/shopify/operations/sitemap.ts`** — extend the `ShopifySitemapType` union. +2. **`app/sitemap.xml/route.ts`** — fetch the new type's `getShopifySitemapPagesCount(...)` and spread its `{type}-{n}` ids into the index alongside the product and collection shards. The index lists only what you add here — it does not discover new types on its own. +3. **`app/sitemap/[shard]/route.ts`** — widen the shard regex and the type mapping so the new `{type}-{n}` segments resolve, then map each item to its URL path. + +## Key files + +| File | Purpose | +| ----------------------------------- | ------------------------------------------------------------ | +| `app/sitemap.xml/route.ts` | Sitemap index — lists every shard | +| `app/sitemap/[shard]/route.ts` | Child sitemaps — `static`, `products-{n}`, `collections-{n}` | +| `lib/shopify/operations/sitemap.ts` | `getShopifySitemapPagesCount`, `getShopifySitemapPage` | +| `app/robots.ts` | Declares the sitemap index as the crawler entry point | diff --git a/apps/docs/content/docs/skills/enable-i18n.mdx b/apps/docs/content/docs/skills/enable-i18n.mdx index e81b565d..a19c429b 100644 --- a/apps/docs/content/docs/skills/enable-i18n.mdx +++ b/apps/docs/content/docs/skills/enable-i18n.mdx @@ -172,7 +172,7 @@ Move every route file from `app/` into `app/[locale]/`: - `app/page.tsx`, `app/error.tsx`, `app/not-found.tsx` → `app/[locale]/...` - `app/about/`, `app/account/`, `app/cart/`, `app/collections/`, `app/products/`, `app/search/` → `app/[locale]/...` -**Stay at `app/`:** `api/`, `sitemap.ts`, `robots.ts`, `global-error.tsx`, `globals.css`, `favicon.ico`. +**Stay at `app/`:** `api/`, `sitemap.xml/`, `sitemap/`, `robots.ts`, `global-error.tsx`, `globals.css`, `favicon.ico`. In the moved layout, fix `import "./globals.css"` → `import "../globals.css"`. @@ -291,18 +291,22 @@ export async function buildAlternates({ pathname, searchParams }: {...}): Promis ### Step 8: Sitemap per-locale entries +Edit `app/sitemap/[shard]/route.ts`. For every resource, emit one `` per enabled locale and add `` siblings inside each `` pointing at the other locale variants. Add `xmlns:xhtml="http://www.w3.org/1999/xhtml"` to the `` opening tag. + ```ts import { enabledLocales } from "@/lib/i18n"; function localizePath(locale: string, pathname: string): string { if (pathname === "/") return `/${locale}`; - const normalized = pathname.startsWith("/") ? pathname : `/${pathname}`; - return `/${locale}${normalized}`; + return `/${locale}${pathname.startsWith("/") ? pathname : `/${pathname}`}`; } -// Inside sitemap(): one entry per locale per page. +// Inside renderShard(): for each item, for each locale, emit a with +// a at the localized path and an per other locale. ``` +`app/sitemap.xml/route.ts` (the index) doesn't need locale handling — it only lists shard URLs, which stay locale-agnostic. + ### Step 9: `next.config.ts` rewrites/redirects on `/:locale/*` Existing markdown content-negotiation rewrites must move their `source` from `/products/:handle` to `/:locale/products/:handle`, etc. Destinations stay at `/md/products/:handle`, `/md/collections/:handle`, and `/md/search` — the handlers read `locale` from query params, not the URL path. Add the locale-prefixed redirect rules from the original config (`/:locale/product*` → `/:locale/products*`). @@ -359,7 +363,8 @@ pnpm build # should pass; routes prerender at /en-US, /en-GB, etc. pnpm dev # then: curl -I / # → 307 /en-US curl -I /products # → 307 /en-US/products -curl /sitemap.xml # → entries with /en-US/... URLs +curl /sitemap.xml # → sitemapindex listing shards +curl /sitemap/products-1.xml # → entries with /en-US/... URLs + xhtml:link alternates curl /en-US # → 200 with ``` diff --git a/apps/docs/content/docs/skills/enable-shopify-cms.mdx b/apps/docs/content/docs/skills/enable-shopify-cms.mdx index 5e3bf91b..37c7364e 100644 --- a/apps/docs/content/docs/skills/enable-shopify-cms.mdx +++ b/apps/docs/content/docs/skills/enable-shopify-cms.mdx @@ -133,7 +133,7 @@ export default async function HomePage() { } ``` -Update `app/pages/[slug]/page.tsx` and `app/sitemap.ts` to use `getMarketingPage` and `getAllMarketingPageSlugs`. +Update `app/pages/[slug]/page.tsx` to use `getMarketingPage` and `getAllMarketingPageSlugs`. To index CMS pages in the sitemap, add a `cms-pages-{n}` shard type to `app/sitemap/[shard]/route.ts` and include it in `app/sitemap.xml/route.ts`. ### 5. Add cache invalidation webhook diff --git a/apps/docs/content/docs/skills/enable-shopify-markets.mdx b/apps/docs/content/docs/skills/enable-shopify-markets.mdx index c84ab92f..893bc0fb 100644 --- a/apps/docs/content/docs/skills/enable-shopify-markets.mdx +++ b/apps/docs/content/docs/skills/enable-shopify-markets.mdx @@ -234,7 +234,7 @@ export const { Link, redirect, usePathname, useRouter } = createNavigation(routi ## Step 5: Move Routes Under `app/[locale]/` -Move all page routes from `app/` into `app/[locale]/`. Keep `api/`, `robots.ts`, `sitemap.ts`, `favicon.ico`, `globals.css`, and `global-error.tsx` at the root level. +Move all page routes from `app/` into `app/[locale]/`. Keep `api/`, `robots.ts`, `sitemap.xml/`, `sitemap/`, `favicon.ico`, `globals.css`, and `global-error.tsx` at the root level. ``` app/layout.tsx → app/[locale]/layout.tsx @@ -343,7 +343,7 @@ Add a `proxy.ts` with next-intl middleware for locale routing: ```ts export const config = { matcher: [ - "/((?!.well-known|api|sitemaps|webhooks|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)", + "/((?!.well-known|api|webhooks|_next/static|_next/image|favicon.ico|sitemap.xml|sitemap/|robots.txt).*)", ], }; @@ -484,9 +484,9 @@ export function buildAlternates({ ## Step 12: Update Sitemap with Per-Locale URLs -**File:** `app/sitemap.ts` +**File:** `app/sitemap/[shard]/route.ts` -Add per-locale URL generation. For each page entry, generate an entry for each enabled locale with `alternates.languages`: +Sitemap children are emitted as raw XML by the shard route handler. For each resource, emit one `` per enabled locale, and inside each `` emit `` siblings pointing at the other locale variants. Add `xmlns:xhtml="http://www.w3.org/1999/xhtml"` to the `` opening tag. ```ts import { enabledLocales, localeSwitchingEnabled } from "@/lib/i18n"; @@ -495,11 +495,12 @@ function localizePath(locale: string, path: string): string { return path === "/" ? `/${locale}` : `/${locale}${path}`; } -// When building sitemap entries, if localeSwitchingEnabled: -// For each path, create entries for all enabled locales -// and add alternates.languages pointing to all locale variants +// Inside renderShard(): if localeSwitchingEnabled, for each item iterate +// enabledLocales and emit a per locale with alternates. ``` +`app/sitemap.xml/route.ts` (the index) doesn't need locale handling — it lists shard URLs which stay locale-agnostic. + --- ## Step 13: Add Locale-Prefixed Redirects diff --git a/apps/template/app/sitemap.ts b/apps/template/app/sitemap.ts deleted file mode 100644 index cac3162f..00000000 --- a/apps/template/app/sitemap.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { MetadataRoute } from "next"; - -import { siteConfig } from "@/lib/config"; -import { getCollections } from "@/lib/shopify/operations/collections"; -import { getAllProductHandles } from "@/lib/shopify/operations/sitemap"; - -function toAbsoluteUrl(pathname: string): string { - return `${siteConfig.url}${pathname}`; -} - -export default async function sitemap(): Promise { - const [collections, products] = await Promise.all([getCollections(), getAllProductHandles()]); - - const homeEntry: MetadataRoute.Sitemap = [ - { - url: toAbsoluteUrl("/"), - }, - ]; - - const collectionEntries: MetadataRoute.Sitemap = collections.map((collection) => ({ - url: toAbsoluteUrl(`/collections/${collection.handle}`), - lastModified: collection.updatedAt, - })); - - const productEntries: MetadataRoute.Sitemap = products.map((product) => ({ - url: toAbsoluteUrl(`/products/${product.handle}`), - lastModified: product.updatedAt, - })); - - return [...homeEntry, ...collectionEntries, ...productEntries]; -} diff --git a/apps/template/app/sitemap.xml/route.ts b/apps/template/app/sitemap.xml/route.ts new file mode 100644 index 00000000..118ee4c9 --- /dev/null +++ b/apps/template/app/sitemap.xml/route.ts @@ -0,0 +1,35 @@ +import { siteConfig } from "@/lib/config"; +import { getShopifySitemapPagesCount } from "@/lib/shopify/operations/sitemap"; + +function escapeXml(value: string): string { + return value.replace(/&/g, "&").replace(//g, ">"); +} + +export async function GET(): Promise { + const [productPages, collectionPages] = await Promise.all([ + getShopifySitemapPagesCount("PRODUCT"), + getShopifySitemapPagesCount("COLLECTION"), + ]); + + const childIds = [ + "static", + ...Array.from({ length: productPages }, (_, i) => `products-${i + 1}`), + ...Array.from({ length: collectionPages }, (_, i) => `collections-${i + 1}`), + ]; + + const entries = childIds + .map( + (id) => ` ${escapeXml(`${siteConfig.url}/sitemap/${id}.xml`)}`, + ) + .join("\n"); + + const body = ` + +${entries} + +`; + + return new Response(body, { + headers: { "Content-Type": "application/xml; charset=utf-8" }, + }); +} diff --git a/apps/template/app/sitemap/[shard]/route.ts b/apps/template/app/sitemap/[shard]/route.ts new file mode 100644 index 00000000..a719b062 --- /dev/null +++ b/apps/template/app/sitemap/[shard]/route.ts @@ -0,0 +1,67 @@ +import { notFound } from "next/navigation"; + +import { siteConfig } from "@/lib/config"; +import { getShopifySitemapPage, type ShopifySitemapType } from "@/lib/shopify/operations/sitemap"; + +function escapeXml(value: string): string { + return value.replace(/&/g, "&").replace(//g, ">"); +} + +function toAbsoluteUrl(pathname: string): string { + return `${siteConfig.url}${pathname}`; +} + +function urlsetWrap(body: string): string { + return ` + +${body} + +`; +} + +function xmlResponse(body: string): Response { + return new Response(body, { + headers: { "Content-Type": "application/xml; charset=utf-8" }, + }); +} + +function renderStatic(): Response { + const entry = ` ${escapeXml(toAbsoluteUrl("/"))}`; + return xmlResponse(urlsetWrap(entry)); +} + +async function renderShard( + type: ShopifySitemapType, + page: number, + segment: string, +): Promise { + const { items } = await getShopifySitemapPage(type, page); + + const entries = items + .map((item) => { + const loc = escapeXml(toAbsoluteUrl(`/${segment}/${item.handle}`)); + const lastmod = escapeXml(item.updatedAt); + return ` \n ${loc}\n ${lastmod}\n `; + }) + .join("\n"); + + return xmlResponse(urlsetWrap(entries)); +} + +export async function GET( + _req: Request, + { params }: { params: Promise<{ shard: string }> }, +): Promise { + const { shard } = await params; + const id = shard.endsWith(".xml") ? shard.slice(0, -".xml".length) : shard; + + if (id === "static") return renderStatic(); + + const match = id.match(/^(products|collections)-(\d+)$/); + if (!match) notFound(); + + const type: ShopifySitemapType = match[1] === "products" ? "PRODUCT" : "COLLECTION"; + const page = Number(match[2]); + + return renderShard(type, page, match[1]); +} diff --git a/apps/template/lib/shopify/operations/sitemap.ts b/apps/template/lib/shopify/operations/sitemap.ts index dbe41fb6..a75ea862 100644 --- a/apps/template/lib/shopify/operations/sitemap.ts +++ b/apps/template/lib/shopify/operations/sitemap.ts @@ -2,61 +2,70 @@ import { cacheLife, cacheTag } from "next/cache"; import { shopifyFetch } from "../fetch"; -interface ProductHandleNode { +export type ShopifySitemapType = "COLLECTION" | "PRODUCT"; + +export interface SitemapResource { handle: string; updatedAt: string; } -interface ProductsPage { - edges: Array<{ node: ProductHandleNode }>; - pageInfo: { - hasNextPage: boolean; - endCursor: string | null; - }; -} +const GET_SITEMAP_PAGES_COUNT_QUERY = ` + query getSitemapPagesCount($type: SitemapType!) { + sitemap(type: $type) { + pagesCount { + count + } + } + } +`; -const GET_PRODUCT_HANDLES_QUERY = ` - query getProductHandlesForSitemap($first: Int!, $after: String) { - products(first: $first, after: $after) { - edges { - node { +const GET_SITEMAP_PAGE_QUERY = ` + query getSitemapPage($type: SitemapType!, $page: Int!) { + sitemap(type: $type) { + resources(page: $page) { + hasNextPage + items { handle updatedAt } } - pageInfo { - hasNextPage - endCursor - } } } `; -const PAGE_SIZE = 250; +function cacheTagFor(type: ShopifySitemapType): string { + return type === "PRODUCT" ? "products" : "collections"; +} -export async function getAllProductHandles(): Promise { +export async function getShopifySitemapPagesCount(type: ShopifySitemapType): Promise { "use cache"; cacheLife("max"); - cacheTag("products"); - - const products: ProductHandleNode[] = []; - let after: string | null = null; - let hasNextPage = true; - - while (hasNextPage) { - const pageData: { products: ProductsPage } = await shopifyFetch({ - operation: "getProductHandlesForSitemap", - query: GET_PRODUCT_HANDLES_QUERY, - variables: { - first: PAGE_SIZE, - after, - }, - }); - - products.push(...pageData.products.edges.map((edge) => edge.node)); - hasNextPage = pageData.products.pageInfo.hasNextPage; - after = pageData.products.pageInfo.endCursor; - } + cacheTag(cacheTagFor(type)); + + const data = await shopifyFetch<{ sitemap: { pagesCount: { count: number } } }>({ + operation: "getSitemapPagesCount", + query: GET_SITEMAP_PAGES_COUNT_QUERY, + variables: { type }, + }); + + return data.sitemap.pagesCount.count; +} + +export async function getShopifySitemapPage( + type: ShopifySitemapType, + page: number, +): Promise<{ hasNextPage: boolean; items: SitemapResource[] }> { + "use cache"; + cacheLife("max"); + cacheTag(cacheTagFor(type)); + + const data = await shopifyFetch<{ + sitemap: { resources: { hasNextPage: boolean; items: SitemapResource[] } }; + }>({ + operation: "getSitemapPage", + query: GET_SITEMAP_PAGE_QUERY, + variables: { type, page }, + }); - return products; + return data.sitemap.resources; } diff --git a/packages/plugin/skills/enable-i18n/SKILL.md b/packages/plugin/skills/enable-i18n/SKILL.md index ede74ff1..cef1a94f 100644 --- a/packages/plugin/skills/enable-i18n/SKILL.md +++ b/packages/plugin/skills/enable-i18n/SKILL.md @@ -167,7 +167,7 @@ Move every route file from `app/` into `app/[locale]/`: - `app/page.tsx`, `app/error.tsx`, `app/not-found.tsx` → `app/[locale]/...` - `app/about/`, `app/account/`, `app/cart/`, `app/collections/`, `app/products/`, `app/search/` → `app/[locale]/...` -**Stay at `app/`:** `api/`, `sitemap.ts`, `robots.ts`, `global-error.tsx`, `globals.css`, `favicon.ico`. +**Stay at `app/`:** `api/`, `sitemap.xml/`, `sitemap/`, `robots.ts`, `global-error.tsx`, `globals.css`, `favicon.ico`. In the moved layout, fix `import "./globals.css"` → `import "../globals.css"`. @@ -286,18 +286,22 @@ export async function buildAlternates({ pathname, searchParams }: {...}): Promis ### Step 8: Sitemap per-locale entries +Edit `app/sitemap/[shard]/route.ts`. For every resource, emit one `` per enabled locale and add `` siblings inside each `` pointing at the other locale variants. Add `xmlns:xhtml="http://www.w3.org/1999/xhtml"` to the `` opening tag. + ```ts import { enabledLocales } from "@/lib/i18n"; function localizePath(locale: string, pathname: string): string { if (pathname === "/") return `/${locale}`; - const normalized = pathname.startsWith("/") ? pathname : `/${pathname}`; - return `/${locale}${normalized}`; + return `/${locale}${pathname.startsWith("/") ? pathname : `/${pathname}`}`; } -// Inside sitemap(): one entry per locale per page. +// Inside renderShard(): for each item, for each locale, emit a with +// a at the localized path and an per other locale. ``` +`app/sitemap.xml/route.ts` (the index) doesn't need locale handling — it only lists shard URLs, which stay locale-agnostic. + ### Step 9: `next.config.ts` rewrites/redirects on `/:locale/*` Existing markdown content-negotiation rewrites must move their `source` from `/products/:handle` to `/:locale/products/:handle`, etc. Destinations stay at `/md/products/:handle`, `/md/collections/:handle`, and `/md/search` — the handlers read `locale` from query params, not the URL path. Add the locale-prefixed redirect rules from the original config (`/:locale/product*` → `/:locale/products*`). @@ -354,7 +358,8 @@ pnpm build # should pass; routes prerender at /en-US, /en-GB, etc. pnpm dev # then: curl -I / # → 307 /en-US curl -I /products # → 307 /en-US/products -curl /sitemap.xml # → entries with /en-US/... URLs +curl /sitemap.xml # → sitemapindex listing shards +curl /sitemap/products-1.xml # → entries with /en-US/... URLs + xhtml:link alternates curl /en-US # → 200 with ``` diff --git a/packages/plugin/skills/enable-shopify-cms/SKILL.md b/packages/plugin/skills/enable-shopify-cms/SKILL.md index 0d7a04d9..a8e9c039 100644 --- a/packages/plugin/skills/enable-shopify-cms/SKILL.md +++ b/packages/plugin/skills/enable-shopify-cms/SKILL.md @@ -122,7 +122,7 @@ export default async function HomePage() { } ``` -Update `app/pages/[slug]/page.tsx` and `app/sitemap.ts` to use `getMarketingPage` and `getAllMarketingPageSlugs`. +Update `app/pages/[slug]/page.tsx` to use `getMarketingPage` and `getAllMarketingPageSlugs`. To index CMS pages in the sitemap, add a `cms-pages-{n}` shard type to `app/sitemap/[shard]/route.ts` and include it in `app/sitemap.xml/route.ts`. ### 5. Add cache invalidation webhook diff --git a/packages/plugin/skills/enable-shopify-markets/SKILL.md b/packages/plugin/skills/enable-shopify-markets/SKILL.md index 20158d44..46b54897 100644 --- a/packages/plugin/skills/enable-shopify-markets/SKILL.md +++ b/packages/plugin/skills/enable-shopify-markets/SKILL.md @@ -227,7 +227,7 @@ export const { Link, redirect, usePathname, useRouter } = createNavigation(routi ## Step 5: Move Routes Under `app/[locale]/` -Move all page routes from `app/` into `app/[locale]/`. Keep `api/`, `robots.ts`, `sitemap.ts`, `favicon.ico`, `globals.css`, and `global-error.tsx` at the root level. +Move all page routes from `app/` into `app/[locale]/`. Keep `api/`, `robots.ts`, `sitemap.xml/`, `sitemap/`, `favicon.ico`, `globals.css`, and `global-error.tsx` at the root level. ``` app/layout.tsx → app/[locale]/layout.tsx @@ -336,7 +336,7 @@ Add a `proxy.ts` with next-intl middleware for locale routing: ```ts export const config = { matcher: [ - "/((?!.well-known|api|sitemaps|webhooks|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)", + "/((?!.well-known|api|webhooks|_next/static|_next/image|favicon.ico|sitemap.xml|sitemap/|robots.txt).*)", ], }; @@ -477,9 +477,9 @@ export function buildAlternates({ ## Step 12: Update Sitemap with Per-Locale URLs -**File:** `app/sitemap.ts` +**File:** `app/sitemap/[shard]/route.ts` -Add per-locale URL generation. For each page entry, generate an entry for each enabled locale with `alternates.languages`: +Sitemap children are emitted as raw XML by the shard route handler. For each resource, emit one `` per enabled locale, and inside each `` emit `` siblings pointing at the other locale variants. Add `xmlns:xhtml="http://www.w3.org/1999/xhtml"` to the `` opening tag. ```ts import { enabledLocales, localeSwitchingEnabled } from "@/lib/i18n"; @@ -488,11 +488,12 @@ function localizePath(locale: string, path: string): string { return path === "/" ? `/${locale}` : `/${locale}${path}`; } -// When building sitemap entries, if localeSwitchingEnabled: -// For each path, create entries for all enabled locales -// and add alternates.languages pointing to all locale variants +// Inside renderShard(): if localeSwitchingEnabled, for each item iterate +// enabledLocales and emit a per locale with alternates. ``` +`app/sitemap.xml/route.ts` (the index) doesn't need locale handling — it lists shard URLs which stay locale-agnostic. + --- ## Step 13: Add Locale-Prefixed Redirects diff --git a/packages/plugin/template-rollout-log/2026-06-04-hydrogen-parity-sitemap.md b/packages/plugin/template-rollout-log/2026-06-04-hydrogen-parity-sitemap.md new file mode 100644 index 00000000..c0f0578d --- /dev/null +++ b/packages/plugin/template-rollout-log/2026-06-04-hydrogen-parity-sitemap.md @@ -0,0 +1,59 @@ +--- +title: Hydrogen-parity paged sitemap for products and collections +changeKey: hydrogen-parity-sitemap +introducedOn: 2026-06-04 +changeType: refactor +defaultAction: review +appliesTo: + - all +paths: + - apps/template/app/sitemap.xml/route.ts + - apps/template/app/sitemap/[shard]/route.ts + - apps/template/lib/shopify/operations/sitemap.ts +--- + +## Summary + +The sitemap now emits an index plus paged child sitemaps backed by Shopify's Storefront `sitemap(type:)` query — the same model Hydrogen uses. The previous implementation loaded every product handle into a single XML response and capped collections at 250. + +- `/sitemap.xml` — sitemap index listing every child shard. +- `/sitemap/static.xml` — the home page (one entry). +- `/sitemap/products-{n}.xml` — up to 250 product URLs per shard, one shard per Shopify sitemap page. +- `/sitemap/collections-{n}.xml` — same shape for collections. + +Each product/collection URL carries `lastmod` from Shopify's `updatedAt`. `robots.ts` still points to `/sitemap.xml` (unchanged). + +The previous `app/sitemap.ts` is gone, along with its `getAllProductHandles` cursor loop. Sitemap generation is now two route handlers (`app/sitemap.xml/route.ts`, `app/sitemap/[shard]/route.ts`) and two operations (`getShopifySitemapPagesCount`, `getShopifySitemapPage`). + +## Why it matters + +- Stores with more than 250 collections were silently truncated — every collection past the cap was invisible to search engines. Now every collection is indexed. +- Stores with tens of thousands of products previously generated a single multi-MB XML that breached Google's 50k-URLs-per-file limit and could OOM during prerender. Sharding to ≤250 entries per child sitemap keeps each file small and well within search engine limits. +- The Storefront `sitemap` query is purpose-built for this — Shopify computes the pagination, so a future Shopify-side optimization (e.g. richer `updatedAt` semantics) flows through automatically. + +## Apply when + +- The storefront still ships the default `/products/[handle]` and `/collections/[handle]` routes at unprefixed paths. +- SEO traffic matters and the catalog is non-trivial (or expected to grow). + +## Safe to skip when + +- The storefront has replaced `app/sitemap.ts` with a hand-rolled implementation that already paginates and shards. +- The catalog is permanently small enough (<250 collections, <10k products) that the old single-file sitemap is sufficient. + +## Why route handlers, not `app/sitemap.ts` + `generateSitemaps` + +Next.js 16 reserves `/sitemap.xml` for `app/sitemap.ts`. With `generateSitemaps`, that file only emits the *children* at `/sitemap/[id].xml` — it does not auto-emit a sitemap index, but it still claims the `/sitemap.xml` URL, which means a parallel `app/sitemap.xml/route.ts` collides. The cleanest fix is to drop `app/sitemap.ts` entirely and own both routes as plain handlers. URL shape is identical to Hydrogen's. + +## Tradeoff + +The change drops the `getAllProductHandles` helper. Any downstream code that imported it must move to `getShopifySitemapPage("PRODUCT", n)` or another product-listing operation. In this template, `app/sitemap.ts` was the only caller. + +Locale alternates, Shopify Markets, pages, blogs, articles, metaobjects, and image-sitemap extensions are all deliberately out of scope. Image sitemaps are a particularly noteworthy gap: Shopify's `Sitemap.image.filepath` is a path fragment, not an absolute URL, and `` requires absolute URLs. Wiring that up requires resolving the shop's CDN base — left as future work. + +## Validation + +1. `pnpm --filter template build` succeeds under `cacheComponents: true`. +2. `curl http://localhost:3000/sitemap.xml` returns a `` listing `static`, `products-{n}`, and `collections-{n}` children. +3. `curl http://localhost:3000/sitemap/products-1.xml` returns a `` with up to 250 entries, each with a ``. +4. Total product count across all `products-*` shards matches the Shopify admin product count. From 1fde2ea8a690ce338f6400842a73925ed90416ae Mon Sep 17 00:00:00 2001 From: Dan Laugharn Date: Mon, 8 Jun 2026 07:43:50 -0500 Subject: [PATCH 13/13] Bumps next --- apps/docs/package.json | 6 +- apps/template/package.json | 4 +- pnpm-lock.yaml | 1224 ++++++++++++++++++------------------ 3 files changed, 617 insertions(+), 617 deletions(-) diff --git a/apps/docs/package.json b/apps/docs/package.json index 4385fedd..8c014fcd 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -18,9 +18,9 @@ "@streamdown/code": "1.1.1", "@tailwindcss/postcss": "4.3.0", "@tailwindcss/typography": "0.5.19", - "@types/mdx": "2.0.13", + "@types/mdx": "2.0.14", "@types/node": "25.9.1", - "@types/react": "19.2.16", + "@types/react": "19.2.17", "@types/react-dom": "19.2.3", "@vercel/analytics": "2.0.1", "@vercel/speed-insights": "2.0.0", @@ -37,7 +37,7 @@ "lucide-react": "1.17.0", "motion": "12.40.0", "nanoid": "5.1.11", - "next": "16.3.0-canary.42", + "next": "16.3.0-canary.45", "next-mdx-remote": "6.0.0", "next-themes": "0.4.6", "oxfmt": "0.53.0", diff --git a/apps/template/package.json b/apps/template/package.json index 60dc873f..e1468642 100644 --- a/apps/template/package.json +++ b/apps/template/package.json @@ -17,7 +17,7 @@ "@tailwindcss/postcss": "4.3.0", "@tailwindcss/typography": "0.5.19", "@types/node": "25.9.1", - "@types/react": "19.2.16", + "@types/react": "19.2.17", "@types/react-dom": "19.2.3", "@vercel/analytics": "2.0.1", "@vercel/speed-insights": "2.0.0", @@ -29,7 +29,7 @@ "cmdk": "1.1.1", "lucide-react": "1.17.0", "nanoid": "5.1.11", - "next": "16.3.0-canary.42", + "next": "16.3.0-canary.45", "next-intl": "4.13.0", "oxfmt": "0.53.0", "oxlint": "1.68.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c441eb32..d724a317 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,23 +42,23 @@ importers: specifier: 0.5.19 version: 0.5.19(tailwindcss@4.3.0) '@types/mdx': - specifier: 2.0.13 - version: 2.0.13 + specifier: 2.0.14 + version: 2.0.14 '@types/node': specifier: 25.9.1 version: 25.9.1 '@types/react': - specifier: 19.2.16 - version: 19.2.16 + specifier: 19.2.17 + version: 19.2.17 '@types/react-dom': specifier: 19.2.3 - version: 19.2.3(@types/react@19.2.16) + version: 19.2.3(@types/react@19.2.17) '@vercel/analytics': specifier: 2.0.1 - version: 2.0.1(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) + version: 2.0.1(next@16.3.0-canary.45(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) '@vercel/speed-insights': specifier: 2.0.0 - version: 2.0.0(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) + version: 2.0.0(next@16.3.0-canary.45(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) ai: specifier: 6.0.197 version: 6.0.197(zod@4.4.3) @@ -70,7 +70,7 @@ importers: version: 2.1.1 cmdk: specifier: 1.1.1 - version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) dexie: specifier: 4.4.3 version: 4.4.3 @@ -82,13 +82,13 @@ importers: version: 5.2.1 fromsrc: specifier: 0.0.31 - version: 0.0.31(@types/react@19.2.16)(katex@0.16.38)(mermaid@11.13.0)(next@16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7) + version: 0.0.31(@types/react@19.2.17)(katex@0.16.38)(mermaid@11.13.0)(next@16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7) geist: specifier: 1.7.2 - version: 1.7.2(next@16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) + version: 1.7.2(next@16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) jotai: specifier: 2.20.0 - version: 2.20.0(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@19.2.16)(react@19.2.7) + version: 2.20.0(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@19.2.17)(react@19.2.7) lucide-react: specifier: 1.17.0 version: 1.17.0(react@19.2.7) @@ -99,11 +99,11 @@ importers: specifier: 5.1.11 version: 5.1.11 next: - specifier: 16.3.0-canary.42 - version: 16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: 16.3.0-canary.45 + version: 16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) next-mdx-remote: specifier: 6.0.0 - version: 6.0.0(@types/react@19.2.16)(react@19.2.7) + version: 6.0.0(@types/react@19.2.17)(react@19.2.7) next-themes: specifier: 0.4.6 version: 0.4.6(react-dom@19.2.7(react@19.2.7))(react@19.2.7) @@ -118,7 +118,7 @@ importers: version: 8.5.15 radix-ui: specifier: 1.4.3 - version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: specifier: 19.2.7 version: 19.2.7 @@ -154,7 +154,7 @@ importers: version: 1.1.6(react@19.2.7) vaul: specifier: 1.1.2 - version: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) zod: specifier: 4.4.3 version: 4.4.3 @@ -180,17 +180,17 @@ importers: specifier: 25.9.1 version: 25.9.1 '@types/react': - specifier: 19.2.16 - version: 19.2.16 + specifier: 19.2.17 + version: 19.2.17 '@types/react-dom': specifier: 19.2.3 - version: 19.2.3(@types/react@19.2.16) + version: 19.2.3(@types/react@19.2.17) '@vercel/analytics': specifier: 2.0.1 - version: 2.0.1(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) + version: 2.0.1(next@16.3.0-canary.45(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) '@vercel/speed-insights': specifier: 2.0.0 - version: 2.0.0(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) + version: 2.0.0(next@16.3.0-canary.45(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) ai: specifier: 6.0.197 version: 6.0.197(zod@4.4.3) @@ -199,7 +199,7 @@ importers: version: 1.0.0 better-auth: specifier: 1.6.14 - version: 1.6.14(@opentelemetry/api@1.9.0)(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) + version: 1.6.14(@opentelemetry/api@1.9.0)(next@16.3.0-canary.45(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)) class-variance-authority: specifier: 0.7.1 version: 0.7.1 @@ -208,7 +208,7 @@ importers: version: 2.1.1 cmdk: specifier: 1.1.1 - version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) lucide-react: specifier: 1.17.0 version: 1.17.0(react@19.2.7) @@ -216,11 +216,11 @@ importers: specifier: 5.1.11 version: 5.1.11 next: - specifier: 16.3.0-canary.42 - version: 16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: 16.3.0-canary.45 + version: 16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) next-intl: specifier: 4.13.0 - version: 4.13.0(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(typescript@6.0.3) + version: 4.13.0(next@16.3.0-canary.45(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(typescript@6.0.3) oxfmt: specifier: 0.53.0 version: 0.53.0 @@ -232,7 +232,7 @@ importers: version: 8.5.15 radix-ui: specifier: 1.4.3 - version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: specifier: 19.2.7 version: 19.2.7 @@ -775,57 +775,57 @@ packages: '@mermaid-js/parser@1.0.1': resolution: {integrity: sha512-opmV19kN1JsK0T6HhhokHpcVkqKpF+x2pPDKKM2ThHtZAB5F4PROopk0amuVYK5qMrIA4erzpNm8gmPNJgMDxQ==} - '@next/env@16.3.0-canary.42': - resolution: {integrity: sha512-UbM5LuTr8ihVr4GiDbrv3n5ps3xxaZCBUOXULRT7ZL+zV3XxNGqnpj3Do72/nNYU3YWZ7OB9FEK2Hg3kto5tbA==} + '@next/env@16.3.0-canary.45': + resolution: {integrity: sha512-Qn4RQpg4cS70Dvdj1CU4KFMAVSA+Kv+c7rIoyVTHIlVAzqFLuEIGqLJDn/BZONQOtKwvHM5HFU29ELNe4GQZPw==} - '@next/swc-darwin-arm64@16.3.0-canary.42': - resolution: {integrity: sha512-u+3OyNzc9AKckgbuMTwLlyZ3jql7fhyDvmqm4TrMNsh1DgHyVvDEUKzHjeZzSEaQBkowA+HBGg553XhdjRVCeg==} + '@next/swc-darwin-arm64@16.3.0-canary.45': + resolution: {integrity: sha512-o5QSYm/CdkiU7V1l2ut5WWzvyoCreUXrcYMiHMuWogdAdkSWzL/g38uGh3aEUsSf+oq9IVdtRZMb+dXA1JiYmA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@16.3.0-canary.42': - resolution: {integrity: sha512-HMPK9Um5vnxfoNhxsd697XWZvS92HODD6r9CwNHrnu2H7A7pW4EcveJ/o1apVeLps7WL6h7Jd8FWNTGFcsDFrA==} + '@next/swc-darwin-x64@16.3.0-canary.45': + resolution: {integrity: sha512-8wjDjXF/qq/TLAbba9ytKsCKUHa4iwyAqJg0ZaBWw0WCVkTNbvEPq/JRVbchqG7SzCss2tpBErpm2NFUnQVWBw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@16.3.0-canary.42': - resolution: {integrity: sha512-QZQLdRNEAYWav2iC/4woLKSHzYtNq0PXpT7qWR7KfnrMG+uIteD3w2x1gUJ3g0w0PIn6LR1BqZOCl/xJeH2OfQ==} + '@next/swc-linux-arm64-gnu@16.3.0-canary.45': + resolution: {integrity: sha512-KDZiPTGUDBgproJqtVMNrtbaId2RrpeFrabWXstUa2QfiY/c7ptu3HQPLd4CJpG+aHzbOq1vF4GBbmImb1eE2A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [glibc] - '@next/swc-linux-arm64-musl@16.3.0-canary.42': - resolution: {integrity: sha512-UYe7DCeZMtiVr9b60VXmRdwqYdKNpg9mixxdWQHljC3yK4ImeHwKgE1ouLwmLMt4OB7N57mlheZcBN1FdDAAYw==} + '@next/swc-linux-arm64-musl@16.3.0-canary.45': + resolution: {integrity: sha512-g2imWF8fZGJo4wOLOVnhy89PfAiq8BdL/UdoX0qMCUDxsDqVOthF47oM8fd6EFwNKLxpqPLRfmj6R8poJQyJ9g==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [musl] - '@next/swc-linux-x64-gnu@16.3.0-canary.42': - resolution: {integrity: sha512-iEvVopTKkolceHpp5Fs0+xWee+wD6r9n+i3qwc+XXTAf7wthPKHbSy5Y2arKj01xzrGGgdmWoJ4v18PbjOH6fA==} + '@next/swc-linux-x64-gnu@16.3.0-canary.45': + resolution: {integrity: sha512-eFsqnRD66eN72KbyXalRMrBvurrjE5anNO27uwit+JcVOIQ96/eE7x0fYKWsonO3g20LkHRqMx7Y+ogF7qO4tw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [glibc] - '@next/swc-linux-x64-musl@16.3.0-canary.42': - resolution: {integrity: sha512-HKF2upUCZOeAS/JzZ5K44CwMefksI8YqinopzWmoS8bf3Y4dxMwaq/Y15r0j/++EIg99k89PugFG4vRvYBQROQ==} + '@next/swc-linux-x64-musl@16.3.0-canary.45': + resolution: {integrity: sha512-/zMi8WqoSZoSywYD2KD/DqpzOrwKAx6scViDbkXmAE0bNu0JLlLfXC434HxVunyExzGTh4HSikv4AqNLOIKsgw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [musl] - '@next/swc-win32-arm64-msvc@16.3.0-canary.42': - resolution: {integrity: sha512-RIPjqRHvRtfzzrXL4K3VVeoXLRjwsthlm4nnoske1tJLT3oBLPpw/yN6Cgu1C5bRSxFtozVJDbRtXTgMCbTsHQ==} + '@next/swc-win32-arm64-msvc@16.3.0-canary.45': + resolution: {integrity: sha512-tpho91u9Fi3Hhl5gDfos2pcZlMzgw/9cVxbs6UOLJf2cvnsxZxeYnGF7Rf+iRC5t2Lr5UWX+4tEF2p0ceqbwOA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@16.3.0-canary.42': - resolution: {integrity: sha512-f9g90g+rdZiylHiz01aKcC2cWW1w3vcIoroVtRO/unl5L2PrW7gAQFcT6AwtcSj8iiSxG4XDcqA/++TMZy9+2w==} + '@next/swc-win32-x64-msvc@16.3.0-canary.45': + resolution: {integrity: sha512-Z0TR7Z8NedmdiSgFSHmzVExtZveZcwRDg9kBZp2FAhGkzpVZXPO7nHSlJTCW6fIBBWXq/SkHwZLYqYFAU7yoUw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -2265,8 +2265,8 @@ packages: '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - '@types/mdx@2.0.13': - resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + '@types/mdx@2.0.14': + resolution: {integrity: sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==} '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -2282,8 +2282,8 @@ packages: peerDependencies: '@types/react': ^19.2.0 - '@types/react@19.2.16': - resolution: {integrity: sha512-esJiCAnl0kfpNdE69f3So4WJUXy95dLZydX0KwK46riIHDzHM7O9Vtf9xCHW0PXIqvgqNrswl522kA/5yx+F4w==} + '@types/react@19.2.17': + resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -3580,8 +3580,8 @@ packages: react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - next@16.3.0-canary.42: - resolution: {integrity: sha512-79C0RdpsrJA0Wxgu/LpIu1cKIqgVGL3AB++/E9o/0cKXJr8tUtgzzrS3xicDAT4C9jtDztFsj73gWZSHjTd8SQ==} + next@16.3.0-canary.45: + resolution: {integrity: sha512-fbBJe6ZVo2JpRUNhVRl41xOu3REqVXqJUkrXDCQrfT6K7rz0Madq0+p8D2XD8Qql3c0Ec9CCB/6ru8heqB7zug==} engines: {node: '>=20.9.0'} hasBin: true peerDependencies: @@ -4850,7 +4850,7 @@ snapshots: '@types/estree': 1.0.8 '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 - '@types/mdx': 2.0.13 + '@types/mdx': 2.0.14 acorn: 8.16.0 collapse-white-space: 2.1.0 devlop: 1.1.0 @@ -4875,40 +4875,40 @@ snapshots: transitivePeerDependencies: - supports-color - '@mdx-js/react@3.1.1(@types/react@19.2.16)(react@19.2.7)': + '@mdx-js/react@3.1.1(@types/react@19.2.17)(react@19.2.7)': dependencies: - '@types/mdx': 2.0.13 - '@types/react': 19.2.16 + '@types/mdx': 2.0.14 + '@types/react': 19.2.17 react: 19.2.7 '@mermaid-js/parser@1.0.1': dependencies: langium: 4.2.1 - '@next/env@16.3.0-canary.42': {} + '@next/env@16.3.0-canary.45': {} - '@next/swc-darwin-arm64@16.3.0-canary.42': + '@next/swc-darwin-arm64@16.3.0-canary.45': optional: true - '@next/swc-darwin-x64@16.3.0-canary.42': + '@next/swc-darwin-x64@16.3.0-canary.45': optional: true - '@next/swc-linux-arm64-gnu@16.3.0-canary.42': + '@next/swc-linux-arm64-gnu@16.3.0-canary.45': optional: true - '@next/swc-linux-arm64-musl@16.3.0-canary.42': + '@next/swc-linux-arm64-musl@16.3.0-canary.45': optional: true - '@next/swc-linux-x64-gnu@16.3.0-canary.42': + '@next/swc-linux-x64-gnu@16.3.0-canary.45': optional: true - '@next/swc-linux-x64-musl@16.3.0-canary.42': + '@next/swc-linux-x64-musl@16.3.0-canary.45': optional: true - '@next/swc-win32-arm64-msvc@16.3.0-canary.42': + '@next/swc-win32-arm64-msvc@16.3.0-canary.45': optional: true - '@next/swc-win32-x64-msvc@16.3.0-canary.42': + '@next/swc-win32-x64-msvc@16.3.0-canary.45': optional: true '@noble/ciphers@2.2.0': {} @@ -5109,762 +5109,762 @@ snapshots: '@radix-ui/primitive@1.1.3': {} - '@radix-ui/react-accessible-icon@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-accessible-icon@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-accordion@1.2.12(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-accordion@1.2.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-alert-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-alert-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-aspect-ratio@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-aspect-ratio@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-avatar@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-avatar@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.17)(react@19.2.7)': dependencies: react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-context@1.1.2(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-context@1.1.2(@types/react@19.2.17)(react@19.2.7)': dependencies: react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) aria-hidden: 1.2.6 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - react-remove-scroll: 2.7.2(@types/react@19.2.16)(react@19.2.7) + react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-direction@1.1.1(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-direction@1.1.1(@types/react@19.2.17)(react@19.2.7)': dependencies: react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.17)(react@19.2.7)': dependencies: react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-form@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-form@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-hover-card@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-hover-card@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-id@1.1.1(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-id@1.1.1(@types/react@19.2.17)(react@19.2.7)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-label@2.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-label@2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) aria-hidden: 1.2.6 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - react-remove-scroll: 2.7.2(@types/react@19.2.16)(react@19.2.7) + react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-menubar@1.1.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-menubar@1.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-navigation-menu@1.2.14(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-navigation-menu@1.2.14(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-one-time-password-field@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-one-time-password-field@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/number': 1.1.1 '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-password-toggle-field@0.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-password-toggle-field@0.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) aria-hidden: 1.2.6 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - react-remove-scroll: 2.7.2(@types/react@19.2.16)(react@19.2.7) + react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@floating-ui/react-dom': 2.1.8(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.17)(react@19.2.7) '@radix-ui/rect': 1.1.1 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-slot': 1.2.4(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-slot': 1.2.4(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-progress@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-progress@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-radio-group@1.3.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-radio-group@1.3.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/number': 1.1.1 '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/number': 1.1.1 '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) aria-hidden: 1.2.6 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - react-remove-scroll: 2.7.2(@types/react@19.2.16)(react@19.2.7) + react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-separator@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-separator@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-slider@1.3.6(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-slider@1.3.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/number': 1.1.1 '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-slot@1.2.3(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-slot@1.2.3(@types/react@19.2.17)(react@19.2.7)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-slot@1.2.4(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-slot@1.2.4(@types/react@19.2.17)(react@19.2.7)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-switch@1.2.6(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-switch@1.2.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-toast@1.2.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-toast@1.2.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-toggle-group@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-toggle-group@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-toggle@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-toggle@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-toolbar@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-toolbar@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-toggle-group': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-toggle-group': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.17)(react@19.2.7)': dependencies: react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.17)(react@19.2.7)': dependencies: - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.17)(react@19.2.7)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.17)(react@19.2.7)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.2.17)(react@19.2.7)': dependencies: react: 19.2.7 use-sync-external-store: 1.6.0(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.17)(react@19.2.7)': dependencies: react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.17)(react@19.2.7)': dependencies: react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.17)(react@19.2.7)': dependencies: '@radix-ui/rect': 1.1.1 react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-use-size@1.1.1(@types/react@19.2.16)(react@19.2.7)': + '@radix-ui/react-use-size@1.1.1(@types/react@19.2.17)(react@19.2.7)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) '@radix-ui/rect@1.1.1': {} @@ -6221,7 +6221,7 @@ snapshots: dependencies: '@types/unist': 3.0.3 - '@types/mdx@2.0.13': {} + '@types/mdx@2.0.14': {} '@types/ms@2.1.0': {} @@ -6231,11 +6231,11 @@ snapshots: dependencies: undici-types: 7.24.6 - '@types/react-dom@19.2.3(@types/react@19.2.16)': + '@types/react-dom@19.2.3(@types/react@19.2.17)': dependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - '@types/react@19.2.16': + '@types/react@19.2.17': dependencies: csstype: 3.2.3 @@ -6253,17 +6253,17 @@ snapshots: d3-selection: 3.0.0 d3-transition: 3.0.1(d3-selection@3.0.0) - '@vercel/analytics@2.0.1(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3))': + '@vercel/analytics@2.0.1(next@16.3.0-canary.45(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3))': optionalDependencies: - next: 16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + next: 16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 vue: 3.5.30(typescript@6.0.3) '@vercel/oidc@3.2.0': {} - '@vercel/speed-insights@2.0.0(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3))': + '@vercel/speed-insights@2.0.0(next@16.3.0-canary.45(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3))': optionalDependencies: - next: 16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + next: 16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 vue: 3.5.30(typescript@6.0.3) @@ -6370,7 +6370,7 @@ snapshots: baseline-browser-mapping@2.10.7: {} - better-auth@1.6.14(@opentelemetry/api@1.9.0)(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)): + better-auth@1.6.14(@opentelemetry/api@1.9.0)(next@16.3.0-canary.45(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(vue@3.5.30(typescript@6.0.3)): dependencies: '@better-auth/core': 1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0) '@better-auth/drizzle-adapter': 1.6.14(@better-auth/core@1.6.14(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.4.3))(jose@6.2.1)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1) @@ -6390,7 +6390,7 @@ snapshots: nanostores: 1.3.0 zod: 4.4.3 optionalDependencies: - next: 16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + next: 16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) vue: 3.5.30(typescript@6.0.3) @@ -6460,12 +6460,12 @@ snapshots: clsx@2.1.1: {} - cmdk@1.1.1(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + cmdk@1.1.1(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) transitivePeerDependencies: @@ -6855,14 +6855,14 @@ snapshots: react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - fromsrc@0.0.31(@types/react@19.2.16)(katex@0.16.38)(mermaid@11.13.0)(next@16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7): + fromsrc@0.0.31(@types/react@19.2.17)(katex@0.16.38)(mermaid@11.13.0)(next@16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7): dependencies: '@mdx-js/mdx': 3.1.1 '@shikijs/rehype': 3.23.0 '@shikijs/transformers': 3.23.0 gray-matter: 4.0.3 - next: 16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - next-mdx-remote: 6.0.0(@types/react@19.2.16)(react@19.2.7) + next: 16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + next-mdx-remote: 6.0.0(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 remark-gfm: 4.0.1 shiki: 3.23.0 @@ -6887,9 +6887,9 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 - geist@1.7.2(next@16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)): + geist@1.7.2(next@16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)): dependencies: - next: 16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + next: 16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) gensync@1.0.0-beta.2: optional: true @@ -7114,11 +7114,11 @@ snapshots: jose@6.2.1: {} - jotai@2.20.0(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@19.2.16)(react@19.2.7): + jotai@2.20.0(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@19.2.17)(react@19.2.7): optionalDependencies: '@babel/core': 7.29.0 '@babel/template': 7.28.6 - '@types/react': 19.2.16 + '@types/react': 19.2.17 react: 19.2.7 js-tokens@4.0.0: {} @@ -7771,14 +7771,14 @@ snapshots: next-intl-swc-plugin-extractor@4.13.0: {} - next-intl@4.13.0(next@16.3.0-canary.42(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(typescript@6.0.3): + next-intl@4.13.0(next@16.3.0-canary.45(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(typescript@6.0.3): dependencies: '@formatjs/intl-localematcher': 0.8.1 '@parcel/watcher': 2.5.6 '@swc/core': 1.15.18 icu-minify: 4.13.0 negotiator: 1.0.0 - next: 16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + next: 16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) next-intl-swc-plugin-extractor: 4.13.0 po-parser: 2.1.1 react: 19.2.7 @@ -7788,11 +7788,11 @@ snapshots: transitivePeerDependencies: - '@swc/helpers' - next-mdx-remote@6.0.0(@types/react@19.2.16)(react@19.2.7): + next-mdx-remote@6.0.0(@types/react@19.2.17)(react@19.2.7): dependencies: '@babel/code-frame': 7.29.0 '@mdx-js/mdx': 3.1.1 - '@mdx-js/react': 3.1.1(@types/react@19.2.16)(react@19.2.7) + '@mdx-js/react': 3.1.1(@types/react@19.2.17)(react@19.2.7) react: 19.2.7 unist-util-remove: 4.0.0 unist-util-visit: 5.1.0 @@ -7807,9 +7807,9 @@ snapshots: react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - next@16.3.0-canary.42(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + next@16.3.0-canary.45(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: - '@next/env': 16.3.0-canary.42 + '@next/env': 16.3.0-canary.45 '@swc/helpers': 0.5.15 baseline-browser-mapping: 2.10.7 caniuse-lite: 1.0.30001778 @@ -7818,14 +7818,14 @@ snapshots: react-dom: 19.2.7(react@19.2.7) styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.7) optionalDependencies: - '@next/swc-darwin-arm64': 16.3.0-canary.42 - '@next/swc-darwin-x64': 16.3.0-canary.42 - '@next/swc-linux-arm64-gnu': 16.3.0-canary.42 - '@next/swc-linux-arm64-musl': 16.3.0-canary.42 - '@next/swc-linux-x64-gnu': 16.3.0-canary.42 - '@next/swc-linux-x64-musl': 16.3.0-canary.42 - '@next/swc-win32-arm64-msvc': 16.3.0-canary.42 - '@next/swc-win32-x64-msvc': 16.3.0-canary.42 + '@next/swc-darwin-arm64': 16.3.0-canary.45 + '@next/swc-darwin-x64': 16.3.0-canary.45 + '@next/swc-linux-arm64-gnu': 16.3.0-canary.45 + '@next/swc-linux-arm64-musl': 16.3.0-canary.45 + '@next/swc-linux-x64-gnu': 16.3.0-canary.45 + '@next/swc-linux-x64-musl': 16.3.0-canary.45 + '@next/swc-win32-arm64-msvc': 16.3.0-canary.45 + '@next/swc-win32-x64-msvc': 16.3.0-canary.45 '@opentelemetry/api': 1.9.0 babel-plugin-react-compiler: 1.0.0 sharp: 0.34.5 @@ -7992,100 +7992,100 @@ snapshots: queue-microtask@1.2.3: {} - radix-ui@1.4.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + radix-ui@1.4.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-accessible-icon': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-alert-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-aspect-ratio': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-avatar': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-checkbox': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-context-menu': 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-form': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-hover-card': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-menubar': 1.1.16(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-navigation-menu': 1.2.14(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-one-time-password-field': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-password-toggle-field': 0.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-progress': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-radio-group': 1.3.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-scroll-area': 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-select': 2.2.6(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slider': 1.3.6(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-switch': 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-toast': 1.2.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-toggle-group': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-toolbar': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.16)(react@19.2.7) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-accessible-icon': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-alert-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-aspect-ratio': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-avatar': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-checkbox': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context-menu': 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-form': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-hover-card': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-menubar': 1.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-navigation-menu': 1.2.14(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-one-time-password-field': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-password-toggle-field': 0.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-progress': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-radio-group': 1.3.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-scroll-area': 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-select': 2.2.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slider': 1.3.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-switch': 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-toast': 1.2.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-toggle-group': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-toolbar': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 - '@types/react-dom': 19.2.3(@types/react@19.2.16) + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) react-dom@19.2.7(react@19.2.7): dependencies: react: 19.2.7 scheduler: 0.27.0 - react-remove-scroll-bar@2.3.8(@types/react@19.2.16)(react@19.2.7): + react-remove-scroll-bar@2.3.8(@types/react@19.2.17)(react@19.2.7): dependencies: react: 19.2.7 - react-style-singleton: 2.2.3(@types/react@19.2.16)(react@19.2.7) + react-style-singleton: 2.2.3(@types/react@19.2.17)(react@19.2.7) tslib: 2.8.1 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - react-remove-scroll@2.7.2(@types/react@19.2.16)(react@19.2.7): + react-remove-scroll@2.7.2(@types/react@19.2.17)(react@19.2.7): dependencies: react: 19.2.7 - react-remove-scroll-bar: 2.3.8(@types/react@19.2.16)(react@19.2.7) - react-style-singleton: 2.2.3(@types/react@19.2.16)(react@19.2.7) + react-remove-scroll-bar: 2.3.8(@types/react@19.2.17)(react@19.2.7) + react-style-singleton: 2.2.3(@types/react@19.2.17)(react@19.2.7) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.2.16)(react@19.2.7) - use-sidecar: 1.1.3(@types/react@19.2.16)(react@19.2.7) + use-callback-ref: 1.3.3(@types/react@19.2.17)(react@19.2.7) + use-sidecar: 1.1.3(@types/react@19.2.17)(react@19.2.7) optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 - react-style-singleton@2.2.3(@types/react@19.2.16)(react@19.2.7): + react-style-singleton@2.2.3(@types/react@19.2.17)(react@19.2.7): dependencies: get-nonce: 1.0.1 react: 19.2.7 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 react@19.2.7: {} @@ -8497,12 +8497,12 @@ snapshots: picocolors: 1.1.1 optional: true - use-callback-ref@1.3.3(@types/react@19.2.16)(react@19.2.7): + use-callback-ref@1.3.3(@types/react@19.2.17)(react@19.2.7): dependencies: react: 19.2.7 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 use-intl@4.13.0(react@19.2.7): dependencies: @@ -8512,13 +8512,13 @@ snapshots: intl-messageformat: 11.1.2 react: 19.2.7 - use-sidecar@1.1.3(@types/react@19.2.16)(react@19.2.7): + use-sidecar@1.1.3(@types/react@19.2.17)(react@19.2.7): dependencies: detect-node-es: 1.1.0 react: 19.2.7 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.2.16 + '@types/react': 19.2.17 use-stick-to-bottom@1.1.6(react@19.2.7): dependencies: @@ -8532,9 +8532,9 @@ snapshots: uuid@11.1.0: {} - vaul@1.1.2(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + vaul@1.1.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.16))(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) transitivePeerDependencies: