@thorprovider/blocks 3.0.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -21
- package/dist/blocks/designs/marketplace-product-card/block.d.ts +12 -0
- package/dist/blocks/designs/marketplace-product-card/block.d.ts.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/block.js +243 -0
- package/dist/blocks/designs/marketplace-product-card/block.js.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/block.mjs +233 -0
- package/dist/blocks/designs/marketplace-product-card/block.mjs.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/index.d.ts +3 -0
- package/dist/blocks/designs/marketplace-product-card/index.d.ts.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/index.js +36 -0
- package/dist/blocks/designs/marketplace-product-card/index.js.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/index.mjs +6 -0
- package/dist/blocks/designs/marketplace-product-card/index.mjs.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.d.ts +13 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.d.ts.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.js +36 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.js.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.mjs +12 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.mjs.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/variants.d.ts +72 -0
- package/dist/blocks/designs/marketplace-product-card/variants.d.ts.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/variants.js +123 -0
- package/dist/blocks/designs/marketplace-product-card/variants.js.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/variants.mjs +89 -0
- package/dist/blocks/designs/marketplace-product-card/variants.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkbox-check.js +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkbox-check.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkbox-check.mjs +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkbox-check.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.d.ts +11 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.js +46 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.mjs +22 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.d.ts +28 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.js +278 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.mjs +260 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.d.ts +12 -9
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.js +49 -71
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.mjs +50 -72
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.js +6 -3
- package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.mjs +6 -3
- package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.d.ts +7 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.js +41 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.mjs +16 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.d.ts +24 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.js +75 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.mjs +58 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.d.ts +3 -2
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.js +9 -2
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.mjs +9 -2
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.d.ts +23 -8
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.js +136 -31
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.mjs +143 -32
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.d.ts +13 -7
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.js +179 -28
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.mjs +180 -29
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.d.ts +20 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.js +199 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.mjs +175 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.d.ts +14 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.js +136 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.mjs +109 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.d.ts +32 -10
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.js +265 -147
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.mjs +272 -148
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.d.ts +13 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.js +74 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.mjs +50 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.d.ts +7 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.js +91 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.mjs +65 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout.d.ts +174 -44
- package/dist/blocks/e-commerce/checkout-forms/checkout.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout.js +532 -108
- package/dist/blocks/e-commerce/checkout-forms/checkout.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout.mjs +542 -109
- package/dist/blocks/e-commerce/checkout-forms/checkout.mjs.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.d.ts.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.js +44 -20
- package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.js.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.mjs +44 -20
- package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.mjs.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar.d.ts.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar.js +21 -10
- package/dist/blocks/e-commerce/navigation/storefront-navbar.js.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar.mjs +21 -10
- package/dist/blocks/e-commerce/navigation/storefront-navbar.mjs.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-card.d.ts.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-card.js +36 -9
- package/dist/blocks/e-commerce/product-list/product-card.js.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-card.mjs +36 -9
- package/dist/blocks/e-commerce/product-list/product-card.mjs.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-showcase-1.d.ts.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-showcase-1.js +7 -2
- package/dist/blocks/e-commerce/product-list/product-showcase-1.js.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-showcase-1.mjs +7 -2
- package/dist/blocks/e-commerce/product-list/product-showcase-1.mjs.map +1 -1
- package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.d.ts.map +1 -1
- package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.js +5 -1
- package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.js.map +1 -1
- package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.mjs +5 -1
- package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.mjs.map +1 -1
- package/dist/blocks/e-commerce/storefront-hero/storefront-hero.d.ts.map +1 -1
- package/dist/blocks/e-commerce/storefront-hero/storefront-hero.js +71 -51
- package/dist/blocks/e-commerce/storefront-hero/storefront-hero.js.map +1 -1
- package/dist/blocks/e-commerce/storefront-hero/storefront-hero.mjs +71 -51
- package/dist/blocks/e-commerce/storefront-hero/storefront-hero.mjs.map +1 -1
- package/dist/blocks/marketing/banners/banner-1.d.ts.map +1 -1
- package/dist/blocks/marketing/banners/banner-1.js +15 -27
- package/dist/blocks/marketing/banners/banner-1.js.map +1 -1
- package/dist/blocks/marketing/banners/banner-1.mjs +16 -28
- package/dist/blocks/marketing/banners/banner-1.mjs.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -1
- package/dist/lib/contracts/marketplace-product-card.d.ts +324 -0
- package/dist/lib/contracts/marketplace-product-card.d.ts.map +1 -0
- package/dist/lib/contracts/marketplace-product-card.js +85 -0
- package/dist/lib/contracts/marketplace-product-card.js.map +1 -0
- package/dist/lib/contracts/marketplace-product-card.mjs +61 -0
- package/dist/lib/contracts/marketplace-product-card.mjs.map +1 -0
- package/dist/lib/contracts.d.ts +1861 -88
- package/dist/lib/contracts.d.ts.map +1 -1
- package/dist/lib/contracts.js +252 -25
- package/dist/lib/contracts.js.map +1 -1
- package/dist/lib/contracts.mjs +208 -5
- package/dist/lib/contracts.mjs.map +1 -1
- package/dist/lib/money-schema.d.ts +19 -0
- package/dist/lib/money-schema.d.ts.map +1 -0
- package/dist/lib/money-schema.js +33 -0
- package/dist/lib/money-schema.js.map +1 -0
- package/dist/lib/money-schema.mjs +9 -0
- package/dist/lib/money-schema.mjs.map +1 -0
- package/dist/lib/motion.d.ts +29 -0
- package/dist/lib/motion.d.ts.map +1 -0
- package/dist/lib/motion.js +65 -0
- package/dist/lib/motion.js.map +1 -0
- package/dist/lib/motion.mjs +41 -0
- package/dist/lib/motion.mjs.map +1 -0
- package/dist/ui/accordion.d.ts +3 -1
- package/dist/ui/accordion.d.ts.map +1 -1
- package/dist/ui/accordion.js +21 -5
- package/dist/ui/accordion.js.map +1 -1
- package/dist/ui/accordion.mjs +21 -5
- package/dist/ui/accordion.mjs.map +1 -1
- package/dist/ui/input-group.d.ts +1 -1
- package/package.json +19 -5
- package/dist/.tsbuildinfo +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useState } from 'react'\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react'\nimport { Minus, Plus, ShoppingBag } from 'lucide-react'\n\nimport { Button } from '../../../ui/button'\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n} from '../../../ui/empty'\nimport { Separator } from '../../../ui/separator'\nimport { SheetClose } from '../../../ui/sheet'\nimport type { Money } from '@thorprovider/types'\nimport { formatMoney } from '../../../lib/money'\n\nexport interface CartItem {\n /** Backend cart line-item id — the stable identity for update/removal. */\n id: string\n name: string\n variant?: string\n price: number\n qty: number\n /** Optional; an absent image is omitted rather than serialized as `\"\"`. */\n image?: string\n /**\n * Canonical backend line amount. Required for truthful rendering in\n * `canonical` mode; when absent/invalid the line shows the unavailable\n * label rather than a numeric fallback.\n */\n lineTotal?: Money\n}\n\nexport type CartSheetState = 'idle' | 'pending' | 'error'\n\nexport interface StorefrontNavbarCartSheetProps {\n items: CartItem[]\n /**\n * Quantity DELTA for a backend cart line-item id. The boundary converts the\n * delta into an absolute quantity against the authoritative current line\n * quantity before mutating the cart.\n */\n onQtyChange: (id: string, delta: number) => void\n /** Remove the backend cart line-item id. */\n onRemove: (id: string) => void\n /** Authoritative backend subtotal. Preferred over any local line math. */\n subtotal?: Money\n /** Shown when an authoritative subtotal is supplied but absent/malformed. */\n subtotalUnavailableLabel?: string\n /** Override money formatting (locale, currency). Defaults to `Money.currencyCode`. */\n formatMoney?: (money: Money) => string\n /** @deprecated legacy numeric formatter; ignored when `subtotal` is supplied. */\n formatPrice?: (value: number) => string\n onCheckout?: () => void\n onViewCart?: () => void\n /**\n * Backend-authoritative rendering. When `true`, each line amount comes from\n * the item's canonical `lineTotal` Money and the sheet never recomputes\n * `price * qty`. When omitted/false, legacy numeric rendering is preserved\n * for standalone consumers.\n */\n canonical?: boolean\n /** Shown in `canonical` mode when a line amount is missing or malformed. */\n lineUnavailableLabel?: string\n /** Cart read/mutation lifecycle. Pending retains confirmed lines; error is recoverable. */\n state?: CartSheetState\n /** Message shown when `state` is `error`. */\n errorLabel?: string\n /** Label for the recovery action in the error state. */\n retryLabel?: string\n /** Recovery action invoked from the error state. */\n onRetry?: () => void\n /** Label shown while `state` is `pending`. */\n pendingLabel?: string\n /** When `true`, the checkout action is suppressed (checkout not installed). */\n checkoutUnavailable?: boolean\n /** When `true`, the checkout action is disabled (cart not ready / invalid amounts). */\n checkoutDisabled?: boolean\n /** When `true`, the review action is suppressed (cart view not installed). */\n viewCartUnavailable?: boolean\n}\n\nconst usdFormatter = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' })\n\n/** Approximate Transitions.dev `delete-with-smoky-dissolve` for list rows (Pro effect). */\nconst smokyExit = {\n opacity: 0,\n y: 10,\n scale: 0.96,\n filter: 'blur(8px)',\n transition: { duration: 0.35, ease: [0.4, 0, 0.2, 1] as const },\n}\n\n/**\n * Transitions.dev `texts-reveal`: lines rise from below with blur, staggered.\n * Exit is a quiet in-place fade — no Y return, no reverse stagger.\n */\nconst revealEase = [0.22, 1, 0.36, 1] as const\nconst revealHidden = { opacity: 0, y: 12, filter: 'blur(3px)' }\nconst revealShown = { opacity: 1, y: 0, filter: 'blur(0px)' }\nconst revealExit = { opacity: 0, y: 0, filter: 'blur(0px)', transition: { duration: 0.2, ease: 'easeOut' as const } }\n\nexport function StorefrontNavbarCartSheet({\n items,\n onQtyChange,\n onRemove,\n subtotal: subtotalProp,\n subtotalUnavailableLabel = '—',\n formatMoney: formatMoneyProp,\n formatPrice,\n onCheckout,\n onViewCart,\n canonical = false,\n lineUnavailableLabel = '—',\n state = 'idle',\n errorLabel = 'No se pudo actualizar el carrito.',\n retryLabel = 'Reintentar',\n onRetry,\n pendingLabel = 'Actualizando el carrito…',\n checkoutUnavailable = false,\n checkoutDisabled = false,\n viewCartUnavailable = false,\n}: StorefrontNavbarCartSheetProps) {\n const reduceMotion = useReducedMotion()\n const format = formatPrice ?? (value => usdFormatter.format(value))\n const localSubtotal = items.reduce((total, item) => total + item.price * item.qty, 0)\n const authoritativeSubtotal = subtotalProp !== undefined ? formatMoney(subtotalProp, formatMoneyProp) : null\n const isEmpty = items.length === 0\n const isPending = state === 'pending'\n const isError = state === 'error'\n /** Wait for the last cart row's exit before revealing empty copy. */\n const [showEmpty, setShowEmpty] = useState(isEmpty)\n\n useEffect(() => {\n if (!isEmpty) {\n setShowEmpty(false)\n }\n }, [isEmpty])\n\n const lineAmount = (item: CartItem): string => {\n if (canonical) {\n if (item.lineTotal === undefined) {\n return lineUnavailableLabel\n }\n return formatMoney(item.lineTotal, formatMoneyProp) ?? lineUnavailableLabel\n }\n return format(item.price * item.qty)\n }\n\n // A confirmed empty cart is only claimed when no read/mutation is in flight\n // and no read error is outstanding; otherwise the sheet shows loading/error.\n const showConfirmedEmpty = showEmpty && !isPending && !isError\n const mutationsDisabled = isPending\n\n return (\n <>\n <div className='relative flex min-h-0 flex-1 flex-col overflow-hidden'>\n {isPending ? (\n <p\n role='status'\n aria-live='polite'\n className='border-border text-muted-foreground border-b px-4 py-2 text-sm'\n >\n {pendingLabel}\n </p>\n ) : null}\n {isError ? (\n <div\n role='alert'\n className='border-border flex items-center justify-between gap-2 border-b px-4 py-2 text-sm'\n >\n <span className='text-destructive'>{errorLabel}</span>\n {onRetry ? (\n <Button variant='ghost' size='sm' onClick={onRetry}>\n {retryLabel}\n </Button>\n ) : null}\n </div>\n ) : null}\n <ul className='flex-1 overflow-y-auto px-4'>\n <AnimatePresence\n initial={false}\n mode='popLayout'\n onExitComplete={() => {\n if (items.length === 0) {\n setShowEmpty(true)\n }\n }}\n >\n {items.map(item => (\n <motion.li\n key={item.id}\n layout={!reduceMotion}\n initial={reduceMotion ? false : { opacity: 0, y: 8, filter: 'blur(4px)' }}\n animate={{ opacity: 1, y: 0, filter: 'blur(0px)' }}\n exit={reduceMotion ? { opacity: 0 } : smokyExit}\n transition={{ duration: 0.28, ease: [0.22, 1, 0.36, 1] }}\n className='border-border flex gap-4 border-b py-4 last:border-b-0'\n style={{ willChange: 'transform, opacity, filter' }}\n >\n {item.image ? (\n <img\n src={item.image || undefined}\n alt=''\n width={80}\n height={96}\n className='bg-muted size-20 shrink-0 rounded-md object-cover'\n />\n ) : (\n <div aria-hidden='true' className='bg-muted size-20 shrink-0 rounded-md' />\n )}\n <div className='flex min-w-0 flex-1 flex-col'>\n <div className='flex items-start justify-between gap-2'>\n <div className='min-w-0'>\n <p className='truncate text-sm font-medium'>{item.name}</p>\n {item.variant ? (\n <p className='text-muted-foreground text-sm'>{item.variant}</p>\n ) : null}\n </div>\n <p className='text-sm font-medium'>{lineAmount(item)}</p>\n </div>\n\n <div className='mt-auto flex items-center justify-between pt-2'>\n <div className='border-border flex items-center rounded-md border'>\n <Button\n variant='ghost'\n size='icon'\n className='size-8 rounded-r-none'\n aria-label={`Decrease quantity, ${item.name}`}\n disabled={mutationsDisabled}\n onClick={() => onQtyChange(item.id, -1)}\n >\n <Minus />\n </Button>\n <span className='w-8 text-center text-sm tabular-nums'>{item.qty}</span>\n <Button\n variant='ghost'\n size='icon'\n className='size-8 rounded-l-none'\n aria-label={`Increase quantity, ${item.name}`}\n disabled={mutationsDisabled}\n onClick={() => onQtyChange(item.id, 1)}\n >\n <Plus />\n </Button>\n </div>\n <Button\n variant='ghost'\n size='sm'\n className='text-muted-foreground hover:text-foreground'\n aria-label={`Remove ${item.name} from cart`}\n disabled={mutationsDisabled}\n onClick={() => onRemove(item.id)}\n >\n Remove\n </Button>\n </div>\n </div>\n </motion.li>\n ))}\n </AnimatePresence>\n </ul>\n\n <AnimatePresence>\n {showConfirmedEmpty ? (\n <motion.div\n key='empty'\n initial={false}\n exit={reduceMotion ? { opacity: 0 } : revealExit}\n className='absolute inset-0'\n >\n <Empty className='h-full border-0'>\n <EmptyHeader>\n <motion.div\n initial={reduceMotion ? false : revealHidden}\n animate={revealShown}\n transition={\n reduceMotion\n ? { duration: 0 }\n : { duration: 0.5, ease: revealEase, delay: 0 }\n }\n style={{ willChange: 'transform, opacity, filter' }}\n >\n <EmptyMedia variant='icon'>\n <ShoppingBag aria-hidden='true' />\n </EmptyMedia>\n </motion.div>\n <motion.div\n initial={reduceMotion ? false : revealHidden}\n animate={revealShown}\n transition={\n reduceMotion\n ? { duration: 0 }\n : { duration: 0.5, ease: revealEase, delay: 0.04 }\n }\n style={{ willChange: 'transform, opacity, filter' }}\n >\n <EmptyTitle>Your cart is empty</EmptyTitle>\n </motion.div>\n <motion.div\n initial={reduceMotion ? false : revealHidden}\n animate={revealShown}\n transition={\n reduceMotion\n ? { duration: 0 }\n : { duration: 0.5, ease: revealEase, delay: 0.08 }\n }\n style={{ willChange: 'transform, opacity, filter' }}\n >\n <EmptyDescription>Once you add something it will show up here.</EmptyDescription>\n </motion.div>\n </EmptyHeader>\n <motion.div\n initial={reduceMotion ? false : revealHidden}\n animate={revealShown}\n transition={\n reduceMotion\n ? { duration: 0 }\n : { duration: 0.5, ease: revealEase, delay: 0.12 }\n }\n style={{ willChange: 'transform, opacity, filter' }}\n >\n <EmptyContent>\n <SheetClose asChild>\n <Button>Continue shopping</Button>\n </SheetClose>\n </EmptyContent>\n </motion.div>\n </Empty>\n </motion.div>\n ) : null}\n </AnimatePresence>\n </div>\n\n {!isEmpty ? (\n <div className='flex flex-col gap-4 p-4'>\n <Separator />\n <div className='flex items-center justify-between text-sm'>\n <span className='text-muted-foreground'>Subtotal</span>\n <span className='font-medium tabular-nums'>\n {canonical || subtotalProp !== undefined\n ? authoritativeSubtotal ?? subtotalUnavailableLabel\n : format(localSubtotal)}\n </span>\n </div>\n <p className='text-muted-foreground text-xs'>Shipping and taxes are calculated at checkout.</p>\n <div className='flex flex-col gap-2'>\n {checkoutUnavailable ? null : (\n <Button\n className='w-full'\n disabled={checkoutDisabled || isPending}\n onClick={onCheckout}\n >\n Checkout\n </Button>\n )}\n {viewCartUnavailable ? null : (\n <Button variant='ghost' className='w-full' onClick={onViewCart}>\n View cart\n </Button>\n )}\n </div>\n </div>\n ) : null}\n </>\n )\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useState } from 'react'\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react'\nimport { Minus, Plus, ShoppingBag } from 'lucide-react'\n\nimport { Button } from '../../../ui/button'\nimport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n} from '../../../ui/empty'\nimport { Separator } from '../../../ui/separator'\nimport { SheetClose } from '../../../ui/sheet'\nimport { MOTION } from '../../../lib/motion'\nimport type { Money } from '@thorprovider/types'\nimport { formatMoney } from '../../../lib/money'\n\nexport interface CartItem {\n /** Backend cart line-item id — the stable identity for update/removal. */\n id: string\n name: string\n variant?: string\n price: number\n qty: number\n /** Optional; an absent image is omitted rather than serialized as `\"\"`. */\n image?: string\n /**\n * Canonical backend line amount. Required for truthful rendering in\n * `canonical` mode; when absent/invalid the line shows the unavailable\n * label rather than a numeric fallback.\n */\n lineTotal?: Money\n}\n\nexport type CartSheetState = 'idle' | 'pending' | 'error'\n\nexport interface StorefrontNavbarCartSheetProps {\n items: CartItem[]\n /**\n * Quantity DELTA for a backend cart line-item id. The boundary converts the\n * delta into an absolute quantity against the authoritative current line\n * quantity before mutating the cart.\n */\n onQtyChange: (id: string, delta: number) => void\n /** Remove the backend cart line-item id. */\n onRemove: (id: string) => void\n /** Authoritative backend subtotal. Preferred over any local line math. */\n subtotal?: Money\n /** Shown when an authoritative subtotal is supplied but absent/malformed. */\n subtotalUnavailableLabel?: string\n /** Override money formatting (locale, currency). Defaults to `Money.currencyCode`. */\n formatMoney?: (money: Money) => string\n /** @deprecated legacy numeric formatter; ignored when `subtotal` is supplied. */\n formatPrice?: (value: number) => string\n onCheckout?: () => void\n onViewCart?: () => void\n /**\n * Backend-authoritative rendering. When `true`, each line amount comes from\n * the item's canonical `lineTotal` Money and the sheet never recomputes\n * `price * qty`. When omitted/false, legacy numeric rendering is preserved\n * for standalone consumers.\n */\n canonical?: boolean\n /** Shown in `canonical` mode when a line amount is missing or malformed. */\n lineUnavailableLabel?: string\n /** Cart read/mutation lifecycle. Pending retains confirmed lines; error is recoverable. */\n state?: CartSheetState\n /** Message shown when `state` is `error`. */\n errorLabel?: string\n /** Label for the recovery action in the error state. */\n retryLabel?: string\n /** Recovery action invoked from the error state. */\n onRetry?: () => void\n /** Label shown while `state` is `pending`. */\n pendingLabel?: string\n /** When `true`, the checkout action is suppressed (checkout not installed). */\n checkoutUnavailable?: boolean\n /** When `true`, the checkout action is disabled (cart not ready / invalid amounts). */\n checkoutDisabled?: boolean\n /** When `true`, the review action is suppressed (cart view not installed). */\n viewCartUnavailable?: boolean\n}\n\nconst usdFormatter = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' })\n\nconst smokyExit = {\n opacity: 0,\n y: MOTION.distancePx.state,\n transition: {\n duration: MOTION.durationSeconds.state,\n ease: MOTION.easing.standard,\n },\n}\n\nconst revealHidden = { opacity: 0, y: MOTION.distancePx.entrance }\nconst revealShown = { opacity: 1, y: 0 }\nconst revealExit = {\n opacity: 0,\n y: 0,\n transition: {\n duration: MOTION.durationSeconds.feedback,\n ease: MOTION.easing.standard,\n },\n}\n\nexport function StorefrontNavbarCartSheet({\n items,\n onQtyChange,\n onRemove,\n subtotal: subtotalProp,\n subtotalUnavailableLabel = '—',\n formatMoney: formatMoneyProp,\n formatPrice,\n onCheckout,\n onViewCart,\n canonical = false,\n lineUnavailableLabel = '—',\n state = 'idle',\n errorLabel = 'No se pudo actualizar el carrito.',\n retryLabel = 'Reintentar',\n onRetry,\n pendingLabel = 'Actualizando el carrito…',\n checkoutUnavailable = false,\n checkoutDisabled = false,\n viewCartUnavailable = false,\n}: StorefrontNavbarCartSheetProps) {\n const reduceMotion = useReducedMotion()\n const format = formatPrice ?? (value => usdFormatter.format(value))\n const localSubtotal = items.reduce((total, item) => total + item.price * item.qty, 0)\n const authoritativeSubtotal = subtotalProp !== undefined ? formatMoney(subtotalProp, formatMoneyProp) : null\n const isEmpty = items.length === 0\n const isPending = state === 'pending'\n const isError = state === 'error'\n /** Wait for the last cart row's exit before revealing empty copy. */\n const [showEmpty, setShowEmpty] = useState(isEmpty)\n\n useEffect(() => {\n if (!isEmpty) {\n setShowEmpty(false)\n }\n }, [isEmpty])\n\n const lineAmount = (item: CartItem): string => {\n if (canonical) {\n if (item.lineTotal === undefined) {\n return lineUnavailableLabel\n }\n return formatMoney(item.lineTotal, formatMoneyProp) ?? lineUnavailableLabel\n }\n return format(item.price * item.qty)\n }\n\n // A confirmed empty cart is only claimed when no read/mutation is in flight\n // and no read error is outstanding; otherwise the sheet shows loading/error.\n const showConfirmedEmpty = showEmpty && !isPending && !isError\n const mutationsDisabled = isPending\n\n return (\n <>\n <div className='relative flex min-h-0 flex-1 flex-col overflow-hidden'>\n {isPending ? (\n <p\n role='status'\n aria-live='polite'\n className='border-border text-muted-foreground border-b px-4 py-2 text-sm'\n >\n {pendingLabel}\n </p>\n ) : null}\n {isError ? (\n <div\n role='alert'\n className='border-border flex items-center justify-between gap-2 border-b px-4 py-2 text-sm'\n >\n <span className='text-destructive'>{errorLabel}</span>\n {onRetry ? (\n <Button variant='ghost' size='sm' onClick={onRetry}>\n {retryLabel}\n </Button>\n ) : null}\n </div>\n ) : null}\n <ul className='flex-1 overflow-y-auto px-4'>\n <AnimatePresence\n initial={false}\n mode='popLayout'\n onExitComplete={() => {\n if (items.length === 0) {\n setShowEmpty(true)\n }\n }}\n >\n {items.map(item => (\n <motion.li\n key={item.id}\n layout={!reduceMotion}\n initial={reduceMotion ? false : { opacity: 0, y: MOTION.distancePx.feedback }}\n animate={{ opacity: 1, y: 0 }}\n exit={reduceMotion ? { opacity: 0 } : smokyExit}\n transition={{ duration: MOTION.durationSeconds.state, ease: MOTION.easing.standard }}\n className='border-border flex gap-4 border-b py-4 last:border-b-0'\n style={{ willChange: 'transform, opacity' }}\n >\n {item.image ? (\n <img\n src={item.image || undefined}\n alt=''\n width={80}\n height={96}\n className='bg-muted size-20 shrink-0 rounded-md object-cover'\n />\n ) : (\n <div aria-hidden='true' className='bg-muted size-20 shrink-0 rounded-md' />\n )}\n <div className='flex min-w-0 flex-1 flex-col'>\n <div className='flex items-start justify-between gap-2'>\n <div className='min-w-0'>\n <p className='truncate text-sm font-medium'>{item.name}</p>\n {item.variant ? (\n <p className='text-muted-foreground text-sm'>{item.variant}</p>\n ) : null}\n </div>\n <p className='text-sm font-medium'>{lineAmount(item)}</p>\n </div>\n\n <div className='mt-auto flex items-center justify-between pt-2'>\n <div className='border-border flex items-center rounded-md border'>\n <Button\n variant='ghost'\n size='icon'\n className='size-8 rounded-r-none'\n aria-label={`Decrease quantity, ${item.name}`}\n disabled={mutationsDisabled}\n onClick={() => onQtyChange(item.id, -1)}\n >\n <Minus />\n </Button>\n <span className='w-8 text-center text-sm tabular-nums'>{item.qty}</span>\n <Button\n variant='ghost'\n size='icon'\n className='size-8 rounded-l-none'\n aria-label={`Increase quantity, ${item.name}`}\n disabled={mutationsDisabled}\n onClick={() => onQtyChange(item.id, 1)}\n >\n <Plus />\n </Button>\n </div>\n <Button\n variant='ghost'\n size='sm'\n className='text-muted-foreground hover:text-foreground'\n aria-label={`Remove ${item.name} from cart`}\n disabled={mutationsDisabled}\n onClick={() => onRemove(item.id)}\n >\n Remove\n </Button>\n </div>\n </div>\n </motion.li>\n ))}\n </AnimatePresence>\n </ul>\n\n <AnimatePresence>\n {showConfirmedEmpty ? (\n <motion.div\n key='empty'\n initial={false}\n exit={reduceMotion ? { opacity: 0 } : revealExit}\n className='absolute inset-0'\n >\n <Empty className='h-full border-0'>\n <EmptyHeader>\n <motion.div\n initial={reduceMotion ? false : revealHidden}\n animate={revealShown}\n transition={\n reduceMotion\n ? { duration: 0 }\n : {\n duration: MOTION.durationSeconds.entrance,\n ease: MOTION.easing.standard,\n delay: MOTION.stagger(0),\n }\n }\n style={{ willChange: 'transform, opacity' }}\n >\n <EmptyMedia variant='icon'>\n <ShoppingBag aria-hidden='true' />\n </EmptyMedia>\n </motion.div>\n <motion.div\n initial={reduceMotion ? false : revealHidden}\n animate={revealShown}\n transition={\n reduceMotion\n ? { duration: 0 }\n : {\n duration: MOTION.durationSeconds.entrance,\n ease: MOTION.easing.standard,\n delay: MOTION.stagger(1),\n }\n }\n style={{ willChange: 'transform, opacity' }}\n >\n <EmptyTitle>Your cart is empty</EmptyTitle>\n </motion.div>\n <motion.div\n initial={reduceMotion ? false : revealHidden}\n animate={revealShown}\n transition={\n reduceMotion\n ? { duration: 0 }\n : {\n duration: MOTION.durationSeconds.entrance,\n ease: MOTION.easing.standard,\n delay: MOTION.stagger(2),\n }\n }\n style={{ willChange: 'transform, opacity' }}\n >\n <EmptyDescription>Once you add something it will show up here.</EmptyDescription>\n </motion.div>\n </EmptyHeader>\n <motion.div\n initial={reduceMotion ? false : revealHidden}\n animate={revealShown}\n transition={\n reduceMotion\n ? { duration: 0 }\n : {\n duration: MOTION.durationSeconds.entrance,\n ease: MOTION.easing.standard,\n delay: MOTION.stagger(3),\n }\n }\n style={{ willChange: 'transform, opacity' }}\n >\n <EmptyContent>\n <SheetClose asChild>\n <Button>Continue shopping</Button>\n </SheetClose>\n </EmptyContent>\n </motion.div>\n </Empty>\n </motion.div>\n ) : null}\n </AnimatePresence>\n </div>\n\n {!isEmpty ? (\n <div className='flex flex-col gap-4 p-4'>\n <Separator />\n <div className='flex items-center justify-between text-sm'>\n <span className='text-muted-foreground'>Subtotal</span>\n <span className='font-medium tabular-nums'>\n {canonical || subtotalProp !== undefined\n ? authoritativeSubtotal ?? subtotalUnavailableLabel\n : format(localSubtotal)}\n </span>\n </div>\n <p className='text-muted-foreground text-xs'>Shipping and taxes are calculated at checkout.</p>\n <div className='flex flex-col gap-2'>\n {checkoutUnavailable ? null : (\n <Button\n className='w-full'\n disabled={checkoutDisabled || isPending}\n onClick={onCheckout}\n >\n Checkout\n </Button>\n )}\n {viewCartUnavailable ? null : (\n <Button variant='ghost' className='w-full' onClick={onViewCart}>\n View cart\n </Button>\n )}\n </div>\n </div>\n ) : null}\n </>\n )\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storefront-navbar.d.ts","sourceRoot":"","sources":["../../../../src/blocks/e-commerce/navigation/storefront-navbar.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"storefront-navbar.d.ts","sourceRoot":"","sources":["../../../../src/blocks/e-commerce/navigation/storefront-navbar.tsx"],"names":[],"mappings":"AAWA,OAAO,EAA+B,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,kCAAkC,CAAA;AACpH,OAAO,EAA6B,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAC9G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAA;AAKjE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AA0B3D,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAA;IACZ,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAgID,MAAM,WAAW,iCAAiC;IAChD,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,OAAe,EAAE,OAAO,EAAE,EAAE,iCAAiC,+BAc3G;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,aAAa,EAAE,CAAA;IAChC;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;OAMG;IACH;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAA;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjD,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,wDAAwD;IACxD,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,6EAA6E;IAC7E,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,sFAAsF;IACtF,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAA;IACtC,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAA;IACpC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAC1C;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,kDAAkD;IAClD,SAAS,CAAC,EAAE,cAAc,CAAA;IAC1B,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,uFAAuF;IACvF,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,sFAAsF;IACtF,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,eAAe,EACf,YAAiB,EACjB,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,UAAiB,EACjB,WAAW,EAAE,eAAe,EAC5B,cAAc,EACd,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,eAAe,EAC5B,QAAQ,EAAE,YAAY,EACtB,QAAQ,EACR,wBAAwB,EACxB,WAAW,EACX,IAAI,EACJ,gBAAgB,EAChB,MAAM,EACN,SAAS,EACT,cAAsB,EACtB,kBAA0B,EAC1B,cAAc,EACd,UAAU,EACV,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,cAAc,EACd,cAAc,EACd,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,GACV,EAAE,qBAAqB,+BAoRvB;AAED,eAAe,gBAAgB,CAAA"}
|
|
@@ -31,6 +31,7 @@ var import_lucide_react = require("lucide-react");
|
|
|
31
31
|
var import_button = require("../../../ui/button.js");
|
|
32
32
|
var import_sheet = require("../../../ui/sheet.js");
|
|
33
33
|
var import_utils = require("../../../lib/utils.js");
|
|
34
|
+
var import_motion = require("../../../lib/motion.js");
|
|
34
35
|
var import_storefront_navbar_account_menu = require("./storefront-navbar-account-menu.js");
|
|
35
36
|
var import_storefront_navbar_cart_sheet = require("./storefront-navbar-cart-sheet.js");
|
|
36
37
|
var import_storefront_navbar_search_bar = require("./storefront-navbar-search-bar.js");
|
|
@@ -115,24 +116,34 @@ function CartBadge({ count }) {
|
|
|
115
116
|
import_react2.motion.span,
|
|
116
117
|
{
|
|
117
118
|
className: "bg-foreground text-background pointer-events-none absolute -top-2.5 -end-3.5 flex size-[1.125rem] items-center justify-center overflow-hidden rounded-full text-[10px] font-medium tabular-nums shadow-sm ring-2 ring-background",
|
|
118
|
-
initial: reduceMotion ? false : {
|
|
119
|
-
|
|
119
|
+
initial: reduceMotion ? false : {
|
|
120
|
+
scale: 0,
|
|
121
|
+
x: -import_motion.MOTION.distancePx.feedback,
|
|
122
|
+
y: import_motion.MOTION.distancePx.state,
|
|
123
|
+
opacity: 0
|
|
124
|
+
},
|
|
125
|
+
animate: { scale: 1, x: 0, y: 0, opacity: 1 },
|
|
120
126
|
exit: reduceMotion ? { opacity: 0 } : {
|
|
121
127
|
scale: 0,
|
|
122
128
|
opacity: 0,
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
transition: {
|
|
130
|
+
duration: import_motion.MOTION.durationSeconds.feedback,
|
|
131
|
+
ease: import_motion.MOTION.easing.standard
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
transition: reduceMotion ? { duration: 0 } : {
|
|
135
|
+
duration: import_motion.MOTION.durationSeconds.state,
|
|
136
|
+
ease: import_motion.MOTION.easing.standard
|
|
125
137
|
},
|
|
126
|
-
|
|
127
|
-
style: { willChange: "transform, opacity, filter" },
|
|
138
|
+
style: { willChange: "transform, opacity" },
|
|
128
139
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react2.AnimatePresence, { mode: "popLayout", initial: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
129
140
|
import_react2.motion.span,
|
|
130
141
|
{
|
|
131
142
|
className: "block",
|
|
132
|
-
initial: reduceMotion ? false : { y:
|
|
133
|
-
animate: { y: 0, opacity: 1
|
|
134
|
-
exit: reduceMotion ? void 0 : { y: -
|
|
135
|
-
transition: { duration:
|
|
143
|
+
initial: reduceMotion ? false : { y: import_motion.MOTION.distancePx.feedback, opacity: 0 },
|
|
144
|
+
animate: { y: 0, opacity: 1 },
|
|
145
|
+
exit: reduceMotion ? void 0 : { y: -import_motion.MOTION.distancePx.feedback, opacity: 0 },
|
|
146
|
+
transition: { duration: import_motion.MOTION.durationSeconds.state, ease: import_motion.MOTION.easing.standard },
|
|
136
147
|
children: count > 99 ? "99+" : count
|
|
137
148
|
},
|
|
138
149
|
count
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/blocks/e-commerce/navigation/storefront-navbar.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react'\nimport { Menu, Search, ShoppingBag, UserRound, RotateCcw, X } from 'lucide-react'\n\nimport { Button } from '../../../ui/button'\nimport { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '../../../ui/sheet'\nimport { cn } from '../../../lib/utils'\n\nimport { StorefrontNavbarAccountMenu, type AccountMenuItem, type StoreUser } from './storefront-navbar-account-menu'\nimport { StorefrontNavbarCartSheet, type CartItem, type CartSheetState } from './storefront-navbar-cart-sheet'\nimport type { UtilityLink } from './storefront-navbar-mobile-nav'\nimport { StorefrontNavbarSearchBar } from './storefront-navbar-search-bar'\nimport { MegaMenu } from './mega-menu'\nimport { MobileCategoryDrawer } from './mobile-category-drawer'\nimport type { MenuItem } from '../../../lib/types/menu'\nimport type { Money } from '@thorprovider/types'\nimport type { StoreCategory } from '../../../lib/contracts'\n\nfunction toMenuItem(category: StoreCategory): MenuItem {\n return {\n id: category.href,\n label: category.label,\n href: category.href,\n children: category.children?.map(toMenuItem),\n }\n}\n\n/**\n * Drawer entries come from three sources (categories, utility links, account\n * link). Hosts may reuse the same href across sources (e.g. a placeholder\n * href), which would produce duplicate React keys if passed through as-is.\n * Dedupe by href so every rendered item gets a unique id.\n */\nfunction uniqueById<T extends { id: string }>(items: T[]): T[] {\n const seen = new Set<string>()\n return items.filter((item) => {\n if (seen.has(item.id)) return false\n seen.add(item.id)\n return true\n })\n}\n\nexport interface LogoAccent {\n /** Trailing segment of `logoText` to render with the accent styling. */\n text: string\n /** Consumer-supplied classes for the accent span (e.g. a brand color token). */\n className?: string\n}\n\nfunction Logo({ text, href, accent }: { text: string; href?: string; accent?: LogoAccent }) {\n const className =\n 'focus-visible:ring-ring flex items-center gap-2 rounded-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none'\n\n const accentText = accent?.text ?? ''\n const hasAccent = accentText.length > 0 && text.endsWith(accentText)\n const baseText = hasAccent ? text.slice(0, text.length - accentText.length) : text\n\n const content = (\n <>\n <svg viewBox='0 0 32 32' aria-hidden='true' className='text-primary size-7' fill='none' xmlns='http://www.w3.org/2000/svg'>\n <path\n d='M26 24.75C26.4142 24.75 26.75 24.4142 26.75 24C26.75 23.5858 26.4142 23.25 26 23.25V24.75ZM26 23.25H11V24.75H26V23.25ZM8.75 21V15H7.25V21H8.75ZM11 23.25C9.75736 23.25 8.75 22.2426 8.75 21H7.25C7.25 23.0711 8.92893 24.75 11 24.75V23.25Z'\n fill='currentColor'\n />\n <path\n d='M1.5 3.25C1.08579 3.25 0.75 3.58579 0.75 4C0.75 4.41421 1.08579 4.75 1.5 4.75V3.25ZM1.5 4.75H6V3.25H1.5V4.75ZM7.25 6V21H8.75V6H7.25ZM6 4.75C6.69036 4.75 7.25 5.30964 7.25 6H8.75C8.75 4.48122 7.51878 3.25 6 3.25V4.75Z'\n fill='currentColor'\n />\n <path\n d='M22 21.75C22.4142 21.75 22.75 21.4142 22.75 21C22.75 20.5858 22.4142 20.25 22 20.25V21.75ZM22 20.25H11V21.75H22V20.25ZM8.75 18V12H7.25V18H8.75ZM11 20.25C9.75736 20.25 8.75 19.2426 8.75 18H7.25C7.25 20.0711 8.92893 21.75 11 21.75V20.25Z'\n fill='currentColor'\n />\n <path\n d='M27.2057 19.754C27.0654 20.1438 26.6357 20.346 26.246 20.2057C25.8562 20.0654 25.654 19.6357 25.7943 19.246L27.2057 19.754ZM30.0361 9.67744L29.3305 9.4234L29.3305 9.4234L30.0361 9.67744ZM25.7943 19.246L29.3305 9.4234L30.7418 9.93148L27.2057 19.754L25.7943 19.246ZM28.1543 7.75L8 7.75V6.25L28.1543 6.25V7.75ZM29.3305 9.4234C29.6237 8.60882 29.0201 7.75 28.1543 7.75V6.25C30.059 6.25 31.3869 8.13941 30.7418 9.93148L29.3305 9.4234Z'\n fill='currentColor'\n />\n <path\n d='M13.5 21.75C13.0858 21.75 12.75 21.4142 12.75 21C12.75 20.5858 13.0858 20.25 13.5 20.25V21.75ZM26.7111 19.009L27.4174 19.2613L27.4174 19.2613L26.7111 19.009ZM13.5 20.25H23.8858V21.75H13.5V20.25ZM26.0048 18.7568L27.7937 13.7477L29.2063 14.2523L27.4174 19.2613L26.0048 18.7568ZM23.8858 20.25C24.8367 20.25 25.6849 19.6522 26.0048 18.7568L27.4174 19.2613C26.8843 20.7537 25.4706 21.75 23.8858 21.75V20.25Z'\n fill='currentColor'\n />\n <path d='M21.1694 10.5806L14.5651 17.1849' stroke='currentColor' strokeWidth='1.5' strokeLinecap='round' />\n <path d='M22.1694 14.5806L18.5632 18.1868' stroke='currentColor' strokeWidth='1.5' strokeLinecap='round' />\n <circle cx='13.1' cy='26.1' r='1.7' stroke='currentColor' strokeWidth='1.2' />\n <circle cx='22.1' cy='26.1' r='1.7' stroke='currentColor' strokeWidth='1.2' />\n </svg>\n <span className='text-base font-semibold tracking-tight'>\n {baseText}\n {hasAccent ? <span className={accent?.className}>{accentText}</span> : null}\n </span>\n </>\n )\n\n if (!href) {\n return <span className={className}>{content}</span>\n }\n\n return (\n <a href={href} className={className}>\n {content}\n </a>\n )\n}\n\ntype CartBadgeProps = {\n count: number\n}\n\n/**\n * Transitions.dev `notification-badge`: diagonal slide + spring pop when the\n * count appears or changes. Positioned outside the bag so it never covers the icon.\n */\nfunction CartBadge({ count }: CartBadgeProps) {\n const reduceMotion = useReducedMotion()\n\n return (\n <AnimatePresence>\n {count > 0 ? (\n <motion.span\n key='badge-shell'\n className='bg-foreground text-background pointer-events-none absolute -top-2.5 -end-3.5 flex size-[1.125rem] items-center justify-center overflow-hidden rounded-full text-[10px] font-medium tabular-nums shadow-sm ring-2 ring-background'\n initial={\n reduceMotion\n ? false\n : { scale: 0, x: -8.2, y: 12.4, opacity: 0, filter: 'blur(2px)' }\n }\n animate={{ scale: 1, x: 0, y: 0, opacity: 1, filter: 'blur(0px)' }}\n exit={\n reduceMotion\n ? { opacity: 0 }\n : {\n scale: 0,\n opacity: 0,\n filter: 'blur(2px)',\n transition: { duration: 0.18, ease: [0.4, 0, 0.2, 1] },\n }\n }\n transition={\n reduceMotion\n ? { duration: 0 }\n : { type: 'spring', stiffness: 520, damping: 18, mass: 0.6 }\n }\n style={{ willChange: 'transform, opacity, filter' }}\n >\n <AnimatePresence mode='popLayout' initial={false}>\n <motion.span\n key={count}\n className='block'\n initial={reduceMotion ? false : { y: 8, opacity: 0, filter: 'blur(2px)' }}\n animate={{ y: 0, opacity: 1, filter: 'blur(0px)' }}\n exit={reduceMotion ? undefined : { y: -8, opacity: 0, filter: 'blur(2px)' }}\n transition={{ duration: 0.22, ease: [0.22, 1, 0.36, 1] }}\n >\n {count > 99 ? '99+' : count}\n </motion.span>\n </AnimatePresence>\n </motion.span>\n ) : null}\n </AnimatePresence>\n )\n}\n\nexport interface StorefrontNavbarAccountRetryProps {\n /** Consumer-owned reconciliation in flight; holds the affordance inert. */\n pending?: boolean\n /** Consumer-owned recovery action. Without it the affordance is inert. */\n onRetry?: () => void\n}\n\n/**\n * Recovery affordance for an unavailable session. The block never resolves the\n * session itself: it surfaces the state and dispatches the consumer's retry.\n * Extracted (hooks-free) so the dispatch is testable without a DOM.\n */\nexport function StorefrontNavbarAccountRetry({ pending = false, onRetry }: StorefrontNavbarAccountRetryProps) {\n return (\n <Button\n variant='ghost'\n size='icon'\n className='size-11'\n disabled={pending || !onRetry}\n aria-label='Retry account session'\n title='Account session unavailable'\n onClick={onRetry}\n >\n <RotateCcw aria-hidden='true' />\n </Button>\n )\n}\n\nexport interface StorefrontNavbarProps {\n storeCategories: StoreCategory[]\n /**\n * Optional note shown in the desktop utility strip. When omitted (or empty)\n * and there are no `utilityLinks`, the strip is not rendered at all, so a\n * block with no optional content paints no empty decorative chrome.\n */\n shippingNote?: string\n utilityLinks: UtilityLink[]\n logoText: string\n logoHref?: string\n /**\n * Optional accent for a trailing segment of `logoText` (e.g. the \"Cuba\" in\n * \"ElectroCuba\"). When omitted, or when `text` is not a trailing segment of\n * `logoText`, the wordmark renders unchanged.\n */\n logoAccent?: LogoAccent\n /** Account destination for anonymous shoppers on every viewport. */\n accountHref?: string\n /**\n * When `false`, no search control is rendered at all — neither the desktop\n * input, the mobile trigger, nor the mobile panel. Defaults to `true` so\n * legacy consumers keep the existing self-contained search. The generated\n * storefront passes `false` while no verified global search contract exists\n * (E2 task 5.4), so no global search is presented as working.\n */\n /**\n * The storefront's current route path. When it matches a destination the link\n * is marked as the current page (accessibly, beyond color alone).\n */\n currentPath?: string\n showSearch?: boolean\n searchQuery?: string\n onSearchChange?: (value: string) => void\n items?: CartItem[]\n /**\n * Quantity DELTA for a backend cart line-item id. The boundary converts the\n * delta into an absolute quantity against the authoritative current line\n * quantity before mutating the cart.\n */\n onQtyChange?: (id: string, delta: number) => void\n /** Remove the backend cart line-item id. */\n onRemove?: (id: string) => void\n /** Authoritative backend subtotal for the mini-cart. */\n subtotal?: Money\n /** Shown when an authoritative subtotal is supplied but absent/malformed. */\n subtotalUnavailableLabel?: string\n /** Override money formatting (locale, currency). Defaults to `Money.currencyCode`. */\n formatMoney?: (money: Money) => string\n user?: StoreUser\n accountMenuItems?: AccountMenuItem[]\n onHelp?: () => void\n onSignOut?: () => void\n accountPending?: boolean\n accountUnavailable?: boolean\n onAccountRetry?: () => void\n onCheckout?: () => void\n onViewCart?: () => void\n /**\n * Controlled visibility for the cart sheet. When provided, the sheet opens\n * and closes from this value and `onCartOpenChange` instead of internal\n * state, so a host can share one cart surface across the navbar trigger and\n * successful add-to-cart. Omit both to keep the legacy uncontrolled sheet.\n */\n cartOpen?: boolean\n /** Change handler paired with `cartOpen` for a controlled sheet. */\n onCartOpenChange?: (open: boolean) => void\n /**\n * Backend-authoritative cart rendering for the sheet. When `true`, line\n * amounts use each item's canonical `lineTotal` Money and never fall back to\n * numeric `price * qty`. Omit for the legacy numeric rendering.\n */\n canonicalCart?: boolean\n /** Cart read/mutation lifecycle for the sheet. */\n cartState?: CartSheetState\n /** Message shown when `cartState` is `error`. */\n cartErrorLabel?: string\n /** Recovery action label for the error state. */\n cartRetryLabel?: string\n /** Recovery action invoked from the error state. */\n onCartRetry?: () => void\n /** When `true`, the sheet's checkout action is suppressed (checkout not installed). */\n checkoutUnavailable?: boolean\n /** When `true`, the sheet's checkout action is disabled (cart not ready). */\n checkoutDisabled?: boolean\n /** When `true`, the sheet's review action is suppressed (cart view not installed). */\n viewCartUnavailable?: boolean\n /**\n * Consumer-supplied classes merged onto the outer `<header>` as the final\n * argument, so a semantic surface such as `bg-brand-nav\n * text-brand-nav-foreground` overrides the default `bg-background`. Purely\n * presentational: no layout, structure, or behavior changes.\n */\n className?: string\n}\n\nexport function StorefrontNavbar({\n storeCategories,\n shippingNote = '',\n utilityLinks,\n logoText,\n logoHref,\n logoAccent,\n accountHref,\n currentPath,\n showSearch = true,\n searchQuery: searchQueryProp,\n onSearchChange,\n items: itemsProp,\n onQtyChange: onQtyChangeProp,\n onRemove: onRemoveProp,\n subtotal,\n subtotalUnavailableLabel,\n formatMoney,\n user,\n accountMenuItems,\n onHelp,\n onSignOut,\n accountPending = false,\n accountUnavailable = false,\n onAccountRetry,\n onCheckout,\n onViewCart,\n cartOpen,\n onCartOpenChange,\n canonicalCart,\n cartState,\n cartErrorLabel,\n cartRetryLabel,\n onCartRetry,\n checkoutUnavailable,\n checkoutDisabled,\n viewCartUnavailable,\n className,\n}: StorefrontNavbarProps) {\n /**\n * Integration seam\n * ----------------\n * Pass cart + search from your storefront, or leave uncontrolled for a\n * self-contained demo. Controlled props win when provided.\n */\n const [internalItems, setInternalItems] = useState<CartItem[]>([])\n const [internalSearch, setInternalSearch] = useState('')\n const [searchOpen, setSearchOpen] = useState(false)\n const [menuOpen, setMenuOpen] = useState(false)\n const searchTriggerRef = useRef<HTMLButtonElement>(null)\n\n const items = itemsProp ?? internalItems\n const searchQuery = searchQueryProp ?? internalSearch\n\n const setSearchQuery = (value: string) => {\n onSearchChange?.(value)\n if (searchQueryProp === undefined) {\n setInternalSearch(value)\n }\n }\n\n const changeQty =\n onQtyChangeProp ??\n ((id: string, delta: number) =>\n setInternalItems(current =>\n current.flatMap(item => {\n if (item.id !== id) {\n return item\n }\n\n const qty = item.qty + delta\n return qty <= 0 ? [] : [{ ...item, qty }]\n }),\n ))\n\n const removeItem =\n onRemoveProp ?? ((id: string) => setInternalItems(current => current.filter(item => item.id !== id)))\n\n const count = useMemo(() => items.reduce((total, item) => total + item.qty, 0), [items])\n\n useEffect(() => {\n if (!showSearch || !searchOpen) {\n return\n }\n\n document.getElementById('store-search-mobile')?.focus()\n }, [searchOpen, showSearch])\n\n const dismissSearch = () => {\n setSearchOpen(false)\n searchTriggerRef.current?.focus()\n }\n\n // When the consumer overrides the header surface via `className`, the nav\n // links inherit its text color and need an explicit hover foreground so\n // `hover:bg-muted` never paints white-on-light; otherwise they keep the\n // default foreground (and the default hover surface).\n const navLinkColor =\n className !== undefined ? 'text-inherit hover:text-foreground' : 'text-foreground'\n // The current page is marked beyond color: an accessible current state plus a\n // visible weight/underline, and nothing when no destination matches.\n const isCurrent = (href?: string) => href !== undefined && href === currentPath\n\n // The desktop utility strip is decorative chrome: it is painted only when it\n // has content (a non-empty note or at least one utility link), never empty.\n const hasUtilityContent = shippingNote.trim().length > 0 || utilityLinks.length > 0\n\n return (\n <header\n className={cn(\n 'border-border sticky top-0 z-40 w-full border-b backdrop-blur-md',\n className ?? 'bg-background/95 supports-backdrop-filter:bg-background/80',\n )}\n >\n {hasUtilityContent ? (\n <div className='bg-foreground text-background hidden lg:block'>\n <div className='mx-auto flex h-9 w-full max-w-7xl items-center justify-between px-4 text-xs tracking-wide sm:px-6 lg:px-8'>\n <p className='text-background/80'>{shippingNote}</p>\n <ul className='flex items-center gap-5'>\n {utilityLinks.map(link => (\n <li key={`${link.href}:${link.label}`}>\n <a\n href={link.href}\n className='text-background/80 hover:text-background transition-colors duration-150'\n >\n {link.label}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n ) : null}\n\n <div className='mx-auto flex h-16 w-full max-w-7xl items-center gap-3 px-4 sm:px-6 lg:px-8'>\n <Button\n variant='ghost'\n size='icon'\n className='lg:hidden'\n aria-label='Open menu'\n aria-expanded={menuOpen}\n onClick={() => setMenuOpen(open => !open)}\n >\n <Menu />\n </Button>\n\n <MobileCategoryDrawer\n categories={uniqueById([\n ...storeCategories.map(toMenuItem),\n ...utilityLinks.map(link => ({ id: link.href, label: link.label, href: link.href })),\n ...(accountHref ? [{ id: accountHref, label: 'Account', href: accountHref }] : []),\n ])}\n collections={[]}\n open={menuOpen}\n onClose={() => setMenuOpen(false)}\n viewAllHref=''\n />\n\n <div className='flex-1 lg:flex-none'>\n <Logo text={logoText} href={logoHref} accent={logoAccent} />\n </div>\n\n <nav aria-label='Store' className='hidden flex-1 lg:block'>\n <ul className='flex items-center gap-0.5'>\n {storeCategories.map(category =>\n category.children && category.children.length > 0 ? (\n <li key={category.href} className='group relative'>\n <a\n href={category.href}\n aria-current={isCurrent(category.href) ? 'page' : undefined}\n className={cn(\n 'hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-2 text-sm font-medium transition-colors duration-150 focus-visible:ring-2 focus-visible:outline-none',\n category.emphasis ? 'text-destructive' : navLinkColor,\n isCurrent(category.href) && 'font-semibold underline underline-offset-4',\n )}\n >\n {category.label}\n </a>\n <div className='invisible absolute left-0 top-full z-50 pt-2 opacity-0 transition-opacity duration-150 group-hover:visible group-hover:opacity-100'>\n <MegaMenu\n categories={[toMenuItem(category)]}\n collections={[]}\n collectionsHref=''\n categoryColumnTitle={category.label}\n />\n </div>\n </li>\n ) : (\n <li key={category.href}>\n <a\n href={category.href}\n aria-current={isCurrent(category.href) ? 'page' : undefined}\n className={cn(\n 'hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-2 text-sm font-medium transition-colors duration-150 focus-visible:ring-2 focus-visible:outline-none',\n category.emphasis ? 'text-destructive' : navLinkColor,\n isCurrent(category.href) && 'font-semibold underline underline-offset-4',\n )}\n >\n {category.label}\n </a>\n </li>\n ),\n )}\n </ul>\n </nav>\n\n <div className='flex items-center gap-1.5'>\n {showSearch ? (\n <>\n <div className='hidden lg:block lg:w-64'>\n <StorefrontNavbarSearchBar\n id='store-search'\n value={searchQuery}\n onValueChange={setSearchQuery}\n />\n </div>\n\n <Button\n ref={searchTriggerRef}\n variant='ghost'\n size='icon'\n className='lg:hidden'\n aria-label='Search products'\n aria-expanded={searchOpen}\n onClick={() => setSearchOpen(open => !open)}\n >\n {searchOpen ? <X /> : <Search />}\n </Button>\n </>\n ) : null}\n\n {accountUnavailable ? (\n <StorefrontNavbarAccountRetry pending={accountPending} onRetry={onAccountRetry} />\n ) : user ? (\n <StorefrontNavbarAccountMenu\n user={user}\n items={accountMenuItems}\n onHelp={onHelp}\n onSignOut={onSignOut}\n pending={accountPending}\n />\n ) : accountHref ? (\n accountPending ? (\n <Button variant='ghost' size='icon' className='size-11' disabled aria-label='Loading account session'>\n <UserRound aria-hidden='true' />\n </Button>\n ) : (\n <Button variant='ghost' size='icon' className='size-11' asChild>\n <a href={accountHref} aria-label='Account' aria-current={isCurrent(accountHref) ? 'page' : undefined}>\n <UserRound aria-hidden='true' />\n </a>\n </Button>\n )\n ) : null}\n\n <Sheet\n {...(cartOpen !== undefined ? { open: cartOpen, onOpenChange: onCartOpenChange } : {})}\n >\n <SheetTrigger asChild>\n <Button\n variant='ghost'\n size='icon'\n className='relative overflow-visible'\n aria-label={`Cart, ${count} ${count === 1 ? 'item' : 'items'}`}\n >\n <ShoppingBag className='size-5' />\n <CartBadge count={count} />\n </Button>\n </SheetTrigger>\n <SheetContent side='right' className='flex w-full max-w-sm flex-col gap-0 p-0'>\n <SheetHeader className='border-border border-b'>\n <SheetTitle className='text-left text-base'>\n Cart{count > 0 ? ` (${count})` : ''}\n </SheetTitle>\n </SheetHeader>\n <StorefrontNavbarCartSheet\n items={items}\n onQtyChange={changeQty}\n onRemove={removeItem}\n subtotal={subtotal}\n subtotalUnavailableLabel={subtotalUnavailableLabel}\n formatMoney={formatMoney}\n onCheckout={onCheckout}\n onViewCart={onViewCart}\n canonical={canonicalCart}\n state={cartState}\n errorLabel={cartErrorLabel}\n retryLabel={cartRetryLabel}\n onRetry={onCartRetry}\n checkoutUnavailable={checkoutUnavailable}\n checkoutDisabled={checkoutDisabled}\n viewCartUnavailable={viewCartUnavailable}\n />\n </SheetContent>\n </Sheet>\n </div>\n </div>\n\n <p aria-live='polite' className='sr-only'>\n {`Cart contains ${count} ${count === 1 ? 'item' : 'items'}`}\n </p>\n\n {showSearch && searchOpen ? (\n <div className='border-border flex flex-col gap-0 border-t p-4 lg:hidden'>\n <StorefrontNavbarSearchBar\n id='store-search-mobile'\n value={searchQuery}\n onValueChange={setSearchQuery}\n onDismiss={dismissSearch}\n />\n </div>\n ) : null}\n </header>\n )\n}\n\nexport default StorefrontNavbar\n"],"mappings":"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","names":["import_react"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/blocks/e-commerce/navigation/storefront-navbar.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react'\nimport { Menu, Search, ShoppingBag, UserRound, RotateCcw, X } from 'lucide-react'\n\nimport { Button } from '../../../ui/button'\nimport { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '../../../ui/sheet'\nimport { cn } from '../../../lib/utils'\nimport { MOTION } from '../../../lib/motion'\n\nimport { StorefrontNavbarAccountMenu, type AccountMenuItem, type StoreUser } from './storefront-navbar-account-menu'\nimport { StorefrontNavbarCartSheet, type CartItem, type CartSheetState } from './storefront-navbar-cart-sheet'\nimport type { UtilityLink } from './storefront-navbar-mobile-nav'\nimport { StorefrontNavbarSearchBar } from './storefront-navbar-search-bar'\nimport { MegaMenu } from './mega-menu'\nimport { MobileCategoryDrawer } from './mobile-category-drawer'\nimport type { MenuItem } from '../../../lib/types/menu'\nimport type { Money } from '@thorprovider/types'\nimport type { StoreCategory } from '../../../lib/contracts'\n\nfunction toMenuItem(category: StoreCategory): MenuItem {\n return {\n id: category.href,\n label: category.label,\n href: category.href,\n children: category.children?.map(toMenuItem),\n }\n}\n\n/**\n * Drawer entries come from three sources (categories, utility links, account\n * link). Hosts may reuse the same href across sources (e.g. a placeholder\n * href), which would produce duplicate React keys if passed through as-is.\n * Dedupe by href so every rendered item gets a unique id.\n */\nfunction uniqueById<T extends { id: string }>(items: T[]): T[] {\n const seen = new Set<string>()\n return items.filter((item) => {\n if (seen.has(item.id)) return false\n seen.add(item.id)\n return true\n })\n}\n\nexport interface LogoAccent {\n /** Trailing segment of `logoText` to render with the accent styling. */\n text: string\n /** Consumer-supplied classes for the accent span (e.g. a brand color token). */\n className?: string\n}\n\nfunction Logo({ text, href, accent }: { text: string; href?: string; accent?: LogoAccent }) {\n const className =\n 'focus-visible:ring-ring flex items-center gap-2 rounded-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none'\n\n const accentText = accent?.text ?? ''\n const hasAccent = accentText.length > 0 && text.endsWith(accentText)\n const baseText = hasAccent ? text.slice(0, text.length - accentText.length) : text\n\n const content = (\n <>\n <svg viewBox='0 0 32 32' aria-hidden='true' className='text-primary size-7' fill='none' xmlns='http://www.w3.org/2000/svg'>\n <path\n d='M26 24.75C26.4142 24.75 26.75 24.4142 26.75 24C26.75 23.5858 26.4142 23.25 26 23.25V24.75ZM26 23.25H11V24.75H26V23.25ZM8.75 21V15H7.25V21H8.75ZM11 23.25C9.75736 23.25 8.75 22.2426 8.75 21H7.25C7.25 23.0711 8.92893 24.75 11 24.75V23.25Z'\n fill='currentColor'\n />\n <path\n d='M1.5 3.25C1.08579 3.25 0.75 3.58579 0.75 4C0.75 4.41421 1.08579 4.75 1.5 4.75V3.25ZM1.5 4.75H6V3.25H1.5V4.75ZM7.25 6V21H8.75V6H7.25ZM6 4.75C6.69036 4.75 7.25 5.30964 7.25 6H8.75C8.75 4.48122 7.51878 3.25 6 3.25V4.75Z'\n fill='currentColor'\n />\n <path\n d='M22 21.75C22.4142 21.75 22.75 21.4142 22.75 21C22.75 20.5858 22.4142 20.25 22 20.25V21.75ZM22 20.25H11V21.75H22V20.25ZM8.75 18V12H7.25V18H8.75ZM11 20.25C9.75736 20.25 8.75 19.2426 8.75 18H7.25C7.25 20.0711 8.92893 21.75 11 21.75V20.25Z'\n fill='currentColor'\n />\n <path\n d='M27.2057 19.754C27.0654 20.1438 26.6357 20.346 26.246 20.2057C25.8562 20.0654 25.654 19.6357 25.7943 19.246L27.2057 19.754ZM30.0361 9.67744L29.3305 9.4234L29.3305 9.4234L30.0361 9.67744ZM25.7943 19.246L29.3305 9.4234L30.7418 9.93148L27.2057 19.754L25.7943 19.246ZM28.1543 7.75L8 7.75V6.25L28.1543 6.25V7.75ZM29.3305 9.4234C29.6237 8.60882 29.0201 7.75 28.1543 7.75V6.25C30.059 6.25 31.3869 8.13941 30.7418 9.93148L29.3305 9.4234Z'\n fill='currentColor'\n />\n <path\n d='M13.5 21.75C13.0858 21.75 12.75 21.4142 12.75 21C12.75 20.5858 13.0858 20.25 13.5 20.25V21.75ZM26.7111 19.009L27.4174 19.2613L27.4174 19.2613L26.7111 19.009ZM13.5 20.25H23.8858V21.75H13.5V20.25ZM26.0048 18.7568L27.7937 13.7477L29.2063 14.2523L27.4174 19.2613L26.0048 18.7568ZM23.8858 20.25C24.8367 20.25 25.6849 19.6522 26.0048 18.7568L27.4174 19.2613C26.8843 20.7537 25.4706 21.75 23.8858 21.75V20.25Z'\n fill='currentColor'\n />\n <path d='M21.1694 10.5806L14.5651 17.1849' stroke='currentColor' strokeWidth='1.5' strokeLinecap='round' />\n <path d='M22.1694 14.5806L18.5632 18.1868' stroke='currentColor' strokeWidth='1.5' strokeLinecap='round' />\n <circle cx='13.1' cy='26.1' r='1.7' stroke='currentColor' strokeWidth='1.2' />\n <circle cx='22.1' cy='26.1' r='1.7' stroke='currentColor' strokeWidth='1.2' />\n </svg>\n <span className='text-base font-semibold tracking-tight'>\n {baseText}\n {hasAccent ? <span className={accent?.className}>{accentText}</span> : null}\n </span>\n </>\n )\n\n if (!href) {\n return <span className={className}>{content}</span>\n }\n\n return (\n <a href={href} className={className}>\n {content}\n </a>\n )\n}\n\ntype CartBadgeProps = {\n count: number\n}\n\n/**\n * Transitions.dev `notification-badge`: diagonal slide + spring pop when the\n * count appears or changes. Positioned outside the bag so it never covers the icon.\n */\nfunction CartBadge({ count }: CartBadgeProps) {\n const reduceMotion = useReducedMotion()\n\n return (\n <AnimatePresence>\n {count > 0 ? (\n <motion.span\n key='badge-shell'\n className='bg-foreground text-background pointer-events-none absolute -top-2.5 -end-3.5 flex size-[1.125rem] items-center justify-center overflow-hidden rounded-full text-[10px] font-medium tabular-nums shadow-sm ring-2 ring-background'\n initial={\n reduceMotion\n ? false\n : {\n scale: 0,\n x: -MOTION.distancePx.feedback,\n y: MOTION.distancePx.state,\n opacity: 0,\n }\n }\n animate={{ scale: 1, x: 0, y: 0, opacity: 1 }}\n exit={\n reduceMotion\n ? { opacity: 0 }\n : {\n scale: 0,\n opacity: 0,\n transition: {\n duration: MOTION.durationSeconds.feedback,\n ease: MOTION.easing.standard,\n },\n }\n }\n transition={\n reduceMotion\n ? { duration: 0 }\n : {\n duration: MOTION.durationSeconds.state,\n ease: MOTION.easing.standard,\n }\n }\n style={{ willChange: 'transform, opacity' }}\n >\n <AnimatePresence mode='popLayout' initial={false}>\n <motion.span\n key={count}\n className='block'\n initial={reduceMotion ? false : { y: MOTION.distancePx.feedback, opacity: 0 }}\n animate={{ y: 0, opacity: 1 }}\n exit={\n reduceMotion\n ? undefined\n : { y: -MOTION.distancePx.feedback, opacity: 0 }\n }\n transition={{ duration: MOTION.durationSeconds.state, ease: MOTION.easing.standard }}\n >\n {count > 99 ? '99+' : count}\n </motion.span>\n </AnimatePresence>\n </motion.span>\n ) : null}\n </AnimatePresence>\n )\n}\n\nexport interface StorefrontNavbarAccountRetryProps {\n /** Consumer-owned reconciliation in flight; holds the affordance inert. */\n pending?: boolean\n /** Consumer-owned recovery action. Without it the affordance is inert. */\n onRetry?: () => void\n}\n\n/**\n * Recovery affordance for an unavailable session. The block never resolves the\n * session itself: it surfaces the state and dispatches the consumer's retry.\n * Extracted (hooks-free) so the dispatch is testable without a DOM.\n */\nexport function StorefrontNavbarAccountRetry({ pending = false, onRetry }: StorefrontNavbarAccountRetryProps) {\n return (\n <Button\n variant='ghost'\n size='icon'\n className='size-11'\n disabled={pending || !onRetry}\n aria-label='Retry account session'\n title='Account session unavailable'\n onClick={onRetry}\n >\n <RotateCcw aria-hidden='true' />\n </Button>\n )\n}\n\nexport interface StorefrontNavbarProps {\n storeCategories: StoreCategory[]\n /**\n * Optional note shown in the desktop utility strip. When omitted (or empty)\n * and there are no `utilityLinks`, the strip is not rendered at all, so a\n * block with no optional content paints no empty decorative chrome.\n */\n shippingNote?: string\n utilityLinks: UtilityLink[]\n logoText: string\n logoHref?: string\n /**\n * Optional accent for a trailing segment of `logoText` (e.g. the \"Cuba\" in\n * \"ElectroCuba\"). When omitted, or when `text` is not a trailing segment of\n * `logoText`, the wordmark renders unchanged.\n */\n logoAccent?: LogoAccent\n /** Account destination for anonymous shoppers on every viewport. */\n accountHref?: string\n /**\n * When `false`, no search control is rendered at all — neither the desktop\n * input, the mobile trigger, nor the mobile panel. Defaults to `true` so\n * legacy consumers keep the existing self-contained search. The generated\n * storefront passes `false` while no verified global search contract exists\n * (E2 task 5.4), so no global search is presented as working.\n */\n /**\n * The storefront's current route path. When it matches a destination the link\n * is marked as the current page (accessibly, beyond color alone).\n */\n currentPath?: string\n showSearch?: boolean\n searchQuery?: string\n onSearchChange?: (value: string) => void\n items?: CartItem[]\n /**\n * Quantity DELTA for a backend cart line-item id. The boundary converts the\n * delta into an absolute quantity against the authoritative current line\n * quantity before mutating the cart.\n */\n onQtyChange?: (id: string, delta: number) => void\n /** Remove the backend cart line-item id. */\n onRemove?: (id: string) => void\n /** Authoritative backend subtotal for the mini-cart. */\n subtotal?: Money\n /** Shown when an authoritative subtotal is supplied but absent/malformed. */\n subtotalUnavailableLabel?: string\n /** Override money formatting (locale, currency). Defaults to `Money.currencyCode`. */\n formatMoney?: (money: Money) => string\n user?: StoreUser\n accountMenuItems?: AccountMenuItem[]\n onHelp?: () => void\n onSignOut?: () => void\n accountPending?: boolean\n accountUnavailable?: boolean\n onAccountRetry?: () => void\n onCheckout?: () => void\n onViewCart?: () => void\n /**\n * Controlled visibility for the cart sheet. When provided, the sheet opens\n * and closes from this value and `onCartOpenChange` instead of internal\n * state, so a host can share one cart surface across the navbar trigger and\n * successful add-to-cart. Omit both to keep the legacy uncontrolled sheet.\n */\n cartOpen?: boolean\n /** Change handler paired with `cartOpen` for a controlled sheet. */\n onCartOpenChange?: (open: boolean) => void\n /**\n * Backend-authoritative cart rendering for the sheet. When `true`, line\n * amounts use each item's canonical `lineTotal` Money and never fall back to\n * numeric `price * qty`. Omit for the legacy numeric rendering.\n */\n canonicalCart?: boolean\n /** Cart read/mutation lifecycle for the sheet. */\n cartState?: CartSheetState\n /** Message shown when `cartState` is `error`. */\n cartErrorLabel?: string\n /** Recovery action label for the error state. */\n cartRetryLabel?: string\n /** Recovery action invoked from the error state. */\n onCartRetry?: () => void\n /** When `true`, the sheet's checkout action is suppressed (checkout not installed). */\n checkoutUnavailable?: boolean\n /** When `true`, the sheet's checkout action is disabled (cart not ready). */\n checkoutDisabled?: boolean\n /** When `true`, the sheet's review action is suppressed (cart view not installed). */\n viewCartUnavailable?: boolean\n /**\n * Consumer-supplied classes merged onto the outer `<header>` as the final\n * argument, so a semantic surface such as `bg-brand-nav\n * text-brand-nav-foreground` overrides the default `bg-background`. Purely\n * presentational: no layout, structure, or behavior changes.\n */\n className?: string\n}\n\nexport function StorefrontNavbar({\n storeCategories,\n shippingNote = '',\n utilityLinks,\n logoText,\n logoHref,\n logoAccent,\n accountHref,\n currentPath,\n showSearch = true,\n searchQuery: searchQueryProp,\n onSearchChange,\n items: itemsProp,\n onQtyChange: onQtyChangeProp,\n onRemove: onRemoveProp,\n subtotal,\n subtotalUnavailableLabel,\n formatMoney,\n user,\n accountMenuItems,\n onHelp,\n onSignOut,\n accountPending = false,\n accountUnavailable = false,\n onAccountRetry,\n onCheckout,\n onViewCart,\n cartOpen,\n onCartOpenChange,\n canonicalCart,\n cartState,\n cartErrorLabel,\n cartRetryLabel,\n onCartRetry,\n checkoutUnavailable,\n checkoutDisabled,\n viewCartUnavailable,\n className,\n}: StorefrontNavbarProps) {\n /**\n * Integration seam\n * ----------------\n * Pass cart + search from your storefront, or leave uncontrolled for a\n * self-contained demo. Controlled props win when provided.\n */\n const [internalItems, setInternalItems] = useState<CartItem[]>([])\n const [internalSearch, setInternalSearch] = useState('')\n const [searchOpen, setSearchOpen] = useState(false)\n const [menuOpen, setMenuOpen] = useState(false)\n const searchTriggerRef = useRef<HTMLButtonElement>(null)\n\n const items = itemsProp ?? internalItems\n const searchQuery = searchQueryProp ?? internalSearch\n\n const setSearchQuery = (value: string) => {\n onSearchChange?.(value)\n if (searchQueryProp === undefined) {\n setInternalSearch(value)\n }\n }\n\n const changeQty =\n onQtyChangeProp ??\n ((id: string, delta: number) =>\n setInternalItems(current =>\n current.flatMap(item => {\n if (item.id !== id) {\n return item\n }\n\n const qty = item.qty + delta\n return qty <= 0 ? [] : [{ ...item, qty }]\n }),\n ))\n\n const removeItem =\n onRemoveProp ?? ((id: string) => setInternalItems(current => current.filter(item => item.id !== id)))\n\n const count = useMemo(() => items.reduce((total, item) => total + item.qty, 0), [items])\n\n useEffect(() => {\n if (!showSearch || !searchOpen) {\n return\n }\n\n document.getElementById('store-search-mobile')?.focus()\n }, [searchOpen, showSearch])\n\n const dismissSearch = () => {\n setSearchOpen(false)\n searchTriggerRef.current?.focus()\n }\n\n // When the consumer overrides the header surface via `className`, the nav\n // links inherit its text color and need an explicit hover foreground so\n // `hover:bg-muted` never paints white-on-light; otherwise they keep the\n // default foreground (and the default hover surface).\n const navLinkColor =\n className !== undefined ? 'text-inherit hover:text-foreground' : 'text-foreground'\n // The current page is marked beyond color: an accessible current state plus a\n // visible weight/underline, and nothing when no destination matches.\n const isCurrent = (href?: string) => href !== undefined && href === currentPath\n\n // The desktop utility strip is decorative chrome: it is painted only when it\n // has content (a non-empty note or at least one utility link), never empty.\n const hasUtilityContent = shippingNote.trim().length > 0 || utilityLinks.length > 0\n\n return (\n <header\n className={cn(\n 'border-border sticky top-0 z-40 w-full border-b backdrop-blur-md',\n className ?? 'bg-background/95 supports-backdrop-filter:bg-background/80',\n )}\n >\n {hasUtilityContent ? (\n <div className='bg-foreground text-background hidden lg:block'>\n <div className='mx-auto flex h-9 w-full max-w-7xl items-center justify-between px-4 text-xs tracking-wide sm:px-6 lg:px-8'>\n <p className='text-background/80'>{shippingNote}</p>\n <ul className='flex items-center gap-5'>\n {utilityLinks.map(link => (\n <li key={`${link.href}:${link.label}`}>\n <a\n href={link.href}\n className='text-background/80 hover:text-background transition-colors duration-150'\n >\n {link.label}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n ) : null}\n\n <div className='mx-auto flex h-16 w-full max-w-7xl items-center gap-3 px-4 sm:px-6 lg:px-8'>\n <Button\n variant='ghost'\n size='icon'\n className='lg:hidden'\n aria-label='Open menu'\n aria-expanded={menuOpen}\n onClick={() => setMenuOpen(open => !open)}\n >\n <Menu />\n </Button>\n\n <MobileCategoryDrawer\n categories={uniqueById([\n ...storeCategories.map(toMenuItem),\n ...utilityLinks.map(link => ({ id: link.href, label: link.label, href: link.href })),\n ...(accountHref ? [{ id: accountHref, label: 'Account', href: accountHref }] : []),\n ])}\n collections={[]}\n open={menuOpen}\n onClose={() => setMenuOpen(false)}\n viewAllHref=''\n />\n\n <div className='flex-1 lg:flex-none'>\n <Logo text={logoText} href={logoHref} accent={logoAccent} />\n </div>\n\n <nav aria-label='Store' className='hidden flex-1 lg:block'>\n <ul className='flex items-center gap-0.5'>\n {storeCategories.map(category =>\n category.children && category.children.length > 0 ? (\n <li key={category.href} className='group relative'>\n <a\n href={category.href}\n aria-current={isCurrent(category.href) ? 'page' : undefined}\n className={cn(\n 'hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-2 text-sm font-medium transition-colors duration-150 focus-visible:ring-2 focus-visible:outline-none',\n category.emphasis ? 'text-destructive' : navLinkColor,\n isCurrent(category.href) && 'font-semibold underline underline-offset-4',\n )}\n >\n {category.label}\n </a>\n <div className='invisible absolute left-0 top-full z-50 pt-2 opacity-0 transition-opacity duration-150 group-hover:visible group-hover:opacity-100'>\n <MegaMenu\n categories={[toMenuItem(category)]}\n collections={[]}\n collectionsHref=''\n categoryColumnTitle={category.label}\n />\n </div>\n </li>\n ) : (\n <li key={category.href}>\n <a\n href={category.href}\n aria-current={isCurrent(category.href) ? 'page' : undefined}\n className={cn(\n 'hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-2 text-sm font-medium transition-colors duration-150 focus-visible:ring-2 focus-visible:outline-none',\n category.emphasis ? 'text-destructive' : navLinkColor,\n isCurrent(category.href) && 'font-semibold underline underline-offset-4',\n )}\n >\n {category.label}\n </a>\n </li>\n ),\n )}\n </ul>\n </nav>\n\n <div className='flex items-center gap-1.5'>\n {showSearch ? (\n <>\n <div className='hidden lg:block lg:w-64'>\n <StorefrontNavbarSearchBar\n id='store-search'\n value={searchQuery}\n onValueChange={setSearchQuery}\n />\n </div>\n\n <Button\n ref={searchTriggerRef}\n variant='ghost'\n size='icon'\n className='lg:hidden'\n aria-label='Search products'\n aria-expanded={searchOpen}\n onClick={() => setSearchOpen(open => !open)}\n >\n {searchOpen ? <X /> : <Search />}\n </Button>\n </>\n ) : null}\n\n {accountUnavailable ? (\n <StorefrontNavbarAccountRetry pending={accountPending} onRetry={onAccountRetry} />\n ) : user ? (\n <StorefrontNavbarAccountMenu\n user={user}\n items={accountMenuItems}\n onHelp={onHelp}\n onSignOut={onSignOut}\n pending={accountPending}\n />\n ) : accountHref ? (\n accountPending ? (\n <Button variant='ghost' size='icon' className='size-11' disabled aria-label='Loading account session'>\n <UserRound aria-hidden='true' />\n </Button>\n ) : (\n <Button variant='ghost' size='icon' className='size-11' asChild>\n <a href={accountHref} aria-label='Account' aria-current={isCurrent(accountHref) ? 'page' : undefined}>\n <UserRound aria-hidden='true' />\n </a>\n </Button>\n )\n ) : null}\n\n <Sheet\n {...(cartOpen !== undefined ? { open: cartOpen, onOpenChange: onCartOpenChange } : {})}\n >\n <SheetTrigger asChild>\n <Button\n variant='ghost'\n size='icon'\n className='relative overflow-visible'\n aria-label={`Cart, ${count} ${count === 1 ? 'item' : 'items'}`}\n >\n <ShoppingBag className='size-5' />\n <CartBadge count={count} />\n </Button>\n </SheetTrigger>\n <SheetContent side='right' className='flex w-full max-w-sm flex-col gap-0 p-0'>\n <SheetHeader className='border-border border-b'>\n <SheetTitle className='text-left text-base'>\n Cart{count > 0 ? ` (${count})` : ''}\n </SheetTitle>\n </SheetHeader>\n <StorefrontNavbarCartSheet\n items={items}\n onQtyChange={changeQty}\n onRemove={removeItem}\n subtotal={subtotal}\n subtotalUnavailableLabel={subtotalUnavailableLabel}\n formatMoney={formatMoney}\n onCheckout={onCheckout}\n onViewCart={onViewCart}\n canonical={canonicalCart}\n state={cartState}\n errorLabel={cartErrorLabel}\n retryLabel={cartRetryLabel}\n onRetry={onCartRetry}\n checkoutUnavailable={checkoutUnavailable}\n checkoutDisabled={checkoutDisabled}\n viewCartUnavailable={viewCartUnavailable}\n />\n </SheetContent>\n </Sheet>\n </div>\n </div>\n\n <p aria-live='polite' className='sr-only'>\n {`Cart contains ${count} ${count === 1 ? 'item' : 'items'}`}\n </p>\n\n {showSearch && searchOpen ? (\n <div className='border-border flex flex-col gap-0 border-t p-4 lg:hidden'>\n <StorefrontNavbarSearchBar\n id='store-search-mobile'\n value={searchQuery}\n onValueChange={setSearchQuery}\n onDismiss={dismissSearch}\n />\n </div>\n ) : null}\n </header>\n )\n}\n\nexport default StorefrontNavbar\n"],"mappings":"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","names":["import_react"]}
|
|
@@ -6,6 +6,7 @@ import { Menu, Search, ShoppingBag, UserRound, RotateCcw, X } from "lucide-react
|
|
|
6
6
|
import { Button } from "../../../ui/button.mjs";
|
|
7
7
|
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "../../../ui/sheet.mjs";
|
|
8
8
|
import { cn } from "../../../lib/utils.mjs";
|
|
9
|
+
import { MOTION } from "../../../lib/motion.mjs";
|
|
9
10
|
import { StorefrontNavbarAccountMenu } from "./storefront-navbar-account-menu.mjs";
|
|
10
11
|
import { StorefrontNavbarCartSheet } from "./storefront-navbar-cart-sheet.mjs";
|
|
11
12
|
import { StorefrontNavbarSearchBar } from "./storefront-navbar-search-bar.mjs";
|
|
@@ -90,24 +91,34 @@ function CartBadge({ count }) {
|
|
|
90
91
|
motion.span,
|
|
91
92
|
{
|
|
92
93
|
className: "bg-foreground text-background pointer-events-none absolute -top-2.5 -end-3.5 flex size-[1.125rem] items-center justify-center overflow-hidden rounded-full text-[10px] font-medium tabular-nums shadow-sm ring-2 ring-background",
|
|
93
|
-
initial: reduceMotion ? false : {
|
|
94
|
-
|
|
94
|
+
initial: reduceMotion ? false : {
|
|
95
|
+
scale: 0,
|
|
96
|
+
x: -MOTION.distancePx.feedback,
|
|
97
|
+
y: MOTION.distancePx.state,
|
|
98
|
+
opacity: 0
|
|
99
|
+
},
|
|
100
|
+
animate: { scale: 1, x: 0, y: 0, opacity: 1 },
|
|
95
101
|
exit: reduceMotion ? { opacity: 0 } : {
|
|
96
102
|
scale: 0,
|
|
97
103
|
opacity: 0,
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
transition: {
|
|
105
|
+
duration: MOTION.durationSeconds.feedback,
|
|
106
|
+
ease: MOTION.easing.standard
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
transition: reduceMotion ? { duration: 0 } : {
|
|
110
|
+
duration: MOTION.durationSeconds.state,
|
|
111
|
+
ease: MOTION.easing.standard
|
|
100
112
|
},
|
|
101
|
-
|
|
102
|
-
style: { willChange: "transform, opacity, filter" },
|
|
113
|
+
style: { willChange: "transform, opacity" },
|
|
103
114
|
children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "popLayout", initial: false, children: /* @__PURE__ */ jsx(
|
|
104
115
|
motion.span,
|
|
105
116
|
{
|
|
106
117
|
className: "block",
|
|
107
|
-
initial: reduceMotion ? false : { y:
|
|
108
|
-
animate: { y: 0, opacity: 1
|
|
109
|
-
exit: reduceMotion ? void 0 : { y: -
|
|
110
|
-
transition: { duration:
|
|
118
|
+
initial: reduceMotion ? false : { y: MOTION.distancePx.feedback, opacity: 0 },
|
|
119
|
+
animate: { y: 0, opacity: 1 },
|
|
120
|
+
exit: reduceMotion ? void 0 : { y: -MOTION.distancePx.feedback, opacity: 0 },
|
|
121
|
+
transition: { duration: MOTION.durationSeconds.state, ease: MOTION.easing.standard },
|
|
111
122
|
children: count > 99 ? "99+" : count
|
|
112
123
|
},
|
|
113
124
|
count
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/blocks/e-commerce/navigation/storefront-navbar.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react'\nimport { Menu, Search, ShoppingBag, UserRound, RotateCcw, X } from 'lucide-react'\n\nimport { Button } from '../../../ui/button'\nimport { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '../../../ui/sheet'\nimport { cn } from '../../../lib/utils'\n\nimport { StorefrontNavbarAccountMenu, type AccountMenuItem, type StoreUser } from './storefront-navbar-account-menu'\nimport { StorefrontNavbarCartSheet, type CartItem, type CartSheetState } from './storefront-navbar-cart-sheet'\nimport type { UtilityLink } from './storefront-navbar-mobile-nav'\nimport { StorefrontNavbarSearchBar } from './storefront-navbar-search-bar'\nimport { MegaMenu } from './mega-menu'\nimport { MobileCategoryDrawer } from './mobile-category-drawer'\nimport type { MenuItem } from '../../../lib/types/menu'\nimport type { Money } from '@thorprovider/types'\nimport type { StoreCategory } from '../../../lib/contracts'\n\nfunction toMenuItem(category: StoreCategory): MenuItem {\n return {\n id: category.href,\n label: category.label,\n href: category.href,\n children: category.children?.map(toMenuItem),\n }\n}\n\n/**\n * Drawer entries come from three sources (categories, utility links, account\n * link). Hosts may reuse the same href across sources (e.g. a placeholder\n * href), which would produce duplicate React keys if passed through as-is.\n * Dedupe by href so every rendered item gets a unique id.\n */\nfunction uniqueById<T extends { id: string }>(items: T[]): T[] {\n const seen = new Set<string>()\n return items.filter((item) => {\n if (seen.has(item.id)) return false\n seen.add(item.id)\n return true\n })\n}\n\nexport interface LogoAccent {\n /** Trailing segment of `logoText` to render with the accent styling. */\n text: string\n /** Consumer-supplied classes for the accent span (e.g. a brand color token). */\n className?: string\n}\n\nfunction Logo({ text, href, accent }: { text: string; href?: string; accent?: LogoAccent }) {\n const className =\n 'focus-visible:ring-ring flex items-center gap-2 rounded-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none'\n\n const accentText = accent?.text ?? ''\n const hasAccent = accentText.length > 0 && text.endsWith(accentText)\n const baseText = hasAccent ? text.slice(0, text.length - accentText.length) : text\n\n const content = (\n <>\n <svg viewBox='0 0 32 32' aria-hidden='true' className='text-primary size-7' fill='none' xmlns='http://www.w3.org/2000/svg'>\n <path\n d='M26 24.75C26.4142 24.75 26.75 24.4142 26.75 24C26.75 23.5858 26.4142 23.25 26 23.25V24.75ZM26 23.25H11V24.75H26V23.25ZM8.75 21V15H7.25V21H8.75ZM11 23.25C9.75736 23.25 8.75 22.2426 8.75 21H7.25C7.25 23.0711 8.92893 24.75 11 24.75V23.25Z'\n fill='currentColor'\n />\n <path\n d='M1.5 3.25C1.08579 3.25 0.75 3.58579 0.75 4C0.75 4.41421 1.08579 4.75 1.5 4.75V3.25ZM1.5 4.75H6V3.25H1.5V4.75ZM7.25 6V21H8.75V6H7.25ZM6 4.75C6.69036 4.75 7.25 5.30964 7.25 6H8.75C8.75 4.48122 7.51878 3.25 6 3.25V4.75Z'\n fill='currentColor'\n />\n <path\n d='M22 21.75C22.4142 21.75 22.75 21.4142 22.75 21C22.75 20.5858 22.4142 20.25 22 20.25V21.75ZM22 20.25H11V21.75H22V20.25ZM8.75 18V12H7.25V18H8.75ZM11 20.25C9.75736 20.25 8.75 19.2426 8.75 18H7.25C7.25 20.0711 8.92893 21.75 11 21.75V20.25Z'\n fill='currentColor'\n />\n <path\n d='M27.2057 19.754C27.0654 20.1438 26.6357 20.346 26.246 20.2057C25.8562 20.0654 25.654 19.6357 25.7943 19.246L27.2057 19.754ZM30.0361 9.67744L29.3305 9.4234L29.3305 9.4234L30.0361 9.67744ZM25.7943 19.246L29.3305 9.4234L30.7418 9.93148L27.2057 19.754L25.7943 19.246ZM28.1543 7.75L8 7.75V6.25L28.1543 6.25V7.75ZM29.3305 9.4234C29.6237 8.60882 29.0201 7.75 28.1543 7.75V6.25C30.059 6.25 31.3869 8.13941 30.7418 9.93148L29.3305 9.4234Z'\n fill='currentColor'\n />\n <path\n d='M13.5 21.75C13.0858 21.75 12.75 21.4142 12.75 21C12.75 20.5858 13.0858 20.25 13.5 20.25V21.75ZM26.7111 19.009L27.4174 19.2613L27.4174 19.2613L26.7111 19.009ZM13.5 20.25H23.8858V21.75H13.5V20.25ZM26.0048 18.7568L27.7937 13.7477L29.2063 14.2523L27.4174 19.2613L26.0048 18.7568ZM23.8858 20.25C24.8367 20.25 25.6849 19.6522 26.0048 18.7568L27.4174 19.2613C26.8843 20.7537 25.4706 21.75 23.8858 21.75V20.25Z'\n fill='currentColor'\n />\n <path d='M21.1694 10.5806L14.5651 17.1849' stroke='currentColor' strokeWidth='1.5' strokeLinecap='round' />\n <path d='M22.1694 14.5806L18.5632 18.1868' stroke='currentColor' strokeWidth='1.5' strokeLinecap='round' />\n <circle cx='13.1' cy='26.1' r='1.7' stroke='currentColor' strokeWidth='1.2' />\n <circle cx='22.1' cy='26.1' r='1.7' stroke='currentColor' strokeWidth='1.2' />\n </svg>\n <span className='text-base font-semibold tracking-tight'>\n {baseText}\n {hasAccent ? <span className={accent?.className}>{accentText}</span> : null}\n </span>\n </>\n )\n\n if (!href) {\n return <span className={className}>{content}</span>\n }\n\n return (\n <a href={href} className={className}>\n {content}\n </a>\n )\n}\n\ntype CartBadgeProps = {\n count: number\n}\n\n/**\n * Transitions.dev `notification-badge`: diagonal slide + spring pop when the\n * count appears or changes. Positioned outside the bag so it never covers the icon.\n */\nfunction CartBadge({ count }: CartBadgeProps) {\n const reduceMotion = useReducedMotion()\n\n return (\n <AnimatePresence>\n {count > 0 ? (\n <motion.span\n key='badge-shell'\n className='bg-foreground text-background pointer-events-none absolute -top-2.5 -end-3.5 flex size-[1.125rem] items-center justify-center overflow-hidden rounded-full text-[10px] font-medium tabular-nums shadow-sm ring-2 ring-background'\n initial={\n reduceMotion\n ? false\n : { scale: 0, x: -8.2, y: 12.4, opacity: 0, filter: 'blur(2px)' }\n }\n animate={{ scale: 1, x: 0, y: 0, opacity: 1, filter: 'blur(0px)' }}\n exit={\n reduceMotion\n ? { opacity: 0 }\n : {\n scale: 0,\n opacity: 0,\n filter: 'blur(2px)',\n transition: { duration: 0.18, ease: [0.4, 0, 0.2, 1] },\n }\n }\n transition={\n reduceMotion\n ? { duration: 0 }\n : { type: 'spring', stiffness: 520, damping: 18, mass: 0.6 }\n }\n style={{ willChange: 'transform, opacity, filter' }}\n >\n <AnimatePresence mode='popLayout' initial={false}>\n <motion.span\n key={count}\n className='block'\n initial={reduceMotion ? false : { y: 8, opacity: 0, filter: 'blur(2px)' }}\n animate={{ y: 0, opacity: 1, filter: 'blur(0px)' }}\n exit={reduceMotion ? undefined : { y: -8, opacity: 0, filter: 'blur(2px)' }}\n transition={{ duration: 0.22, ease: [0.22, 1, 0.36, 1] }}\n >\n {count > 99 ? '99+' : count}\n </motion.span>\n </AnimatePresence>\n </motion.span>\n ) : null}\n </AnimatePresence>\n )\n}\n\nexport interface StorefrontNavbarAccountRetryProps {\n /** Consumer-owned reconciliation in flight; holds the affordance inert. */\n pending?: boolean\n /** Consumer-owned recovery action. Without it the affordance is inert. */\n onRetry?: () => void\n}\n\n/**\n * Recovery affordance for an unavailable session. The block never resolves the\n * session itself: it surfaces the state and dispatches the consumer's retry.\n * Extracted (hooks-free) so the dispatch is testable without a DOM.\n */\nexport function StorefrontNavbarAccountRetry({ pending = false, onRetry }: StorefrontNavbarAccountRetryProps) {\n return (\n <Button\n variant='ghost'\n size='icon'\n className='size-11'\n disabled={pending || !onRetry}\n aria-label='Retry account session'\n title='Account session unavailable'\n onClick={onRetry}\n >\n <RotateCcw aria-hidden='true' />\n </Button>\n )\n}\n\nexport interface StorefrontNavbarProps {\n storeCategories: StoreCategory[]\n /**\n * Optional note shown in the desktop utility strip. When omitted (or empty)\n * and there are no `utilityLinks`, the strip is not rendered at all, so a\n * block with no optional content paints no empty decorative chrome.\n */\n shippingNote?: string\n utilityLinks: UtilityLink[]\n logoText: string\n logoHref?: string\n /**\n * Optional accent for a trailing segment of `logoText` (e.g. the \"Cuba\" in\n * \"ElectroCuba\"). When omitted, or when `text` is not a trailing segment of\n * `logoText`, the wordmark renders unchanged.\n */\n logoAccent?: LogoAccent\n /** Account destination for anonymous shoppers on every viewport. */\n accountHref?: string\n /**\n * When `false`, no search control is rendered at all — neither the desktop\n * input, the mobile trigger, nor the mobile panel. Defaults to `true` so\n * legacy consumers keep the existing self-contained search. The generated\n * storefront passes `false` while no verified global search contract exists\n * (E2 task 5.4), so no global search is presented as working.\n */\n /**\n * The storefront's current route path. When it matches a destination the link\n * is marked as the current page (accessibly, beyond color alone).\n */\n currentPath?: string\n showSearch?: boolean\n searchQuery?: string\n onSearchChange?: (value: string) => void\n items?: CartItem[]\n /**\n * Quantity DELTA for a backend cart line-item id. The boundary converts the\n * delta into an absolute quantity against the authoritative current line\n * quantity before mutating the cart.\n */\n onQtyChange?: (id: string, delta: number) => void\n /** Remove the backend cart line-item id. */\n onRemove?: (id: string) => void\n /** Authoritative backend subtotal for the mini-cart. */\n subtotal?: Money\n /** Shown when an authoritative subtotal is supplied but absent/malformed. */\n subtotalUnavailableLabel?: string\n /** Override money formatting (locale, currency). Defaults to `Money.currencyCode`. */\n formatMoney?: (money: Money) => string\n user?: StoreUser\n accountMenuItems?: AccountMenuItem[]\n onHelp?: () => void\n onSignOut?: () => void\n accountPending?: boolean\n accountUnavailable?: boolean\n onAccountRetry?: () => void\n onCheckout?: () => void\n onViewCart?: () => void\n /**\n * Controlled visibility for the cart sheet. When provided, the sheet opens\n * and closes from this value and `onCartOpenChange` instead of internal\n * state, so a host can share one cart surface across the navbar trigger and\n * successful add-to-cart. Omit both to keep the legacy uncontrolled sheet.\n */\n cartOpen?: boolean\n /** Change handler paired with `cartOpen` for a controlled sheet. */\n onCartOpenChange?: (open: boolean) => void\n /**\n * Backend-authoritative cart rendering for the sheet. When `true`, line\n * amounts use each item's canonical `lineTotal` Money and never fall back to\n * numeric `price * qty`. Omit for the legacy numeric rendering.\n */\n canonicalCart?: boolean\n /** Cart read/mutation lifecycle for the sheet. */\n cartState?: CartSheetState\n /** Message shown when `cartState` is `error`. */\n cartErrorLabel?: string\n /** Recovery action label for the error state. */\n cartRetryLabel?: string\n /** Recovery action invoked from the error state. */\n onCartRetry?: () => void\n /** When `true`, the sheet's checkout action is suppressed (checkout not installed). */\n checkoutUnavailable?: boolean\n /** When `true`, the sheet's checkout action is disabled (cart not ready). */\n checkoutDisabled?: boolean\n /** When `true`, the sheet's review action is suppressed (cart view not installed). */\n viewCartUnavailable?: boolean\n /**\n * Consumer-supplied classes merged onto the outer `<header>` as the final\n * argument, so a semantic surface such as `bg-brand-nav\n * text-brand-nav-foreground` overrides the default `bg-background`. Purely\n * presentational: no layout, structure, or behavior changes.\n */\n className?: string\n}\n\nexport function StorefrontNavbar({\n storeCategories,\n shippingNote = '',\n utilityLinks,\n logoText,\n logoHref,\n logoAccent,\n accountHref,\n currentPath,\n showSearch = true,\n searchQuery: searchQueryProp,\n onSearchChange,\n items: itemsProp,\n onQtyChange: onQtyChangeProp,\n onRemove: onRemoveProp,\n subtotal,\n subtotalUnavailableLabel,\n formatMoney,\n user,\n accountMenuItems,\n onHelp,\n onSignOut,\n accountPending = false,\n accountUnavailable = false,\n onAccountRetry,\n onCheckout,\n onViewCart,\n cartOpen,\n onCartOpenChange,\n canonicalCart,\n cartState,\n cartErrorLabel,\n cartRetryLabel,\n onCartRetry,\n checkoutUnavailable,\n checkoutDisabled,\n viewCartUnavailable,\n className,\n}: StorefrontNavbarProps) {\n /**\n * Integration seam\n * ----------------\n * Pass cart + search from your storefront, or leave uncontrolled for a\n * self-contained demo. Controlled props win when provided.\n */\n const [internalItems, setInternalItems] = useState<CartItem[]>([])\n const [internalSearch, setInternalSearch] = useState('')\n const [searchOpen, setSearchOpen] = useState(false)\n const [menuOpen, setMenuOpen] = useState(false)\n const searchTriggerRef = useRef<HTMLButtonElement>(null)\n\n const items = itemsProp ?? internalItems\n const searchQuery = searchQueryProp ?? internalSearch\n\n const setSearchQuery = (value: string) => {\n onSearchChange?.(value)\n if (searchQueryProp === undefined) {\n setInternalSearch(value)\n }\n }\n\n const changeQty =\n onQtyChangeProp ??\n ((id: string, delta: number) =>\n setInternalItems(current =>\n current.flatMap(item => {\n if (item.id !== id) {\n return item\n }\n\n const qty = item.qty + delta\n return qty <= 0 ? [] : [{ ...item, qty }]\n }),\n ))\n\n const removeItem =\n onRemoveProp ?? ((id: string) => setInternalItems(current => current.filter(item => item.id !== id)))\n\n const count = useMemo(() => items.reduce((total, item) => total + item.qty, 0), [items])\n\n useEffect(() => {\n if (!showSearch || !searchOpen) {\n return\n }\n\n document.getElementById('store-search-mobile')?.focus()\n }, [searchOpen, showSearch])\n\n const dismissSearch = () => {\n setSearchOpen(false)\n searchTriggerRef.current?.focus()\n }\n\n // When the consumer overrides the header surface via `className`, the nav\n // links inherit its text color and need an explicit hover foreground so\n // `hover:bg-muted` never paints white-on-light; otherwise they keep the\n // default foreground (and the default hover surface).\n const navLinkColor =\n className !== undefined ? 'text-inherit hover:text-foreground' : 'text-foreground'\n // The current page is marked beyond color: an accessible current state plus a\n // visible weight/underline, and nothing when no destination matches.\n const isCurrent = (href?: string) => href !== undefined && href === currentPath\n\n // The desktop utility strip is decorative chrome: it is painted only when it\n // has content (a non-empty note or at least one utility link), never empty.\n const hasUtilityContent = shippingNote.trim().length > 0 || utilityLinks.length > 0\n\n return (\n <header\n className={cn(\n 'border-border sticky top-0 z-40 w-full border-b backdrop-blur-md',\n className ?? 'bg-background/95 supports-backdrop-filter:bg-background/80',\n )}\n >\n {hasUtilityContent ? (\n <div className='bg-foreground text-background hidden lg:block'>\n <div className='mx-auto flex h-9 w-full max-w-7xl items-center justify-between px-4 text-xs tracking-wide sm:px-6 lg:px-8'>\n <p className='text-background/80'>{shippingNote}</p>\n <ul className='flex items-center gap-5'>\n {utilityLinks.map(link => (\n <li key={`${link.href}:${link.label}`}>\n <a\n href={link.href}\n className='text-background/80 hover:text-background transition-colors duration-150'\n >\n {link.label}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n ) : null}\n\n <div className='mx-auto flex h-16 w-full max-w-7xl items-center gap-3 px-4 sm:px-6 lg:px-8'>\n <Button\n variant='ghost'\n size='icon'\n className='lg:hidden'\n aria-label='Open menu'\n aria-expanded={menuOpen}\n onClick={() => setMenuOpen(open => !open)}\n >\n <Menu />\n </Button>\n\n <MobileCategoryDrawer\n categories={uniqueById([\n ...storeCategories.map(toMenuItem),\n ...utilityLinks.map(link => ({ id: link.href, label: link.label, href: link.href })),\n ...(accountHref ? [{ id: accountHref, label: 'Account', href: accountHref }] : []),\n ])}\n collections={[]}\n open={menuOpen}\n onClose={() => setMenuOpen(false)}\n viewAllHref=''\n />\n\n <div className='flex-1 lg:flex-none'>\n <Logo text={logoText} href={logoHref} accent={logoAccent} />\n </div>\n\n <nav aria-label='Store' className='hidden flex-1 lg:block'>\n <ul className='flex items-center gap-0.5'>\n {storeCategories.map(category =>\n category.children && category.children.length > 0 ? (\n <li key={category.href} className='group relative'>\n <a\n href={category.href}\n aria-current={isCurrent(category.href) ? 'page' : undefined}\n className={cn(\n 'hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-2 text-sm font-medium transition-colors duration-150 focus-visible:ring-2 focus-visible:outline-none',\n category.emphasis ? 'text-destructive' : navLinkColor,\n isCurrent(category.href) && 'font-semibold underline underline-offset-4',\n )}\n >\n {category.label}\n </a>\n <div className='invisible absolute left-0 top-full z-50 pt-2 opacity-0 transition-opacity duration-150 group-hover:visible group-hover:opacity-100'>\n <MegaMenu\n categories={[toMenuItem(category)]}\n collections={[]}\n collectionsHref=''\n categoryColumnTitle={category.label}\n />\n </div>\n </li>\n ) : (\n <li key={category.href}>\n <a\n href={category.href}\n aria-current={isCurrent(category.href) ? 'page' : undefined}\n className={cn(\n 'hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-2 text-sm font-medium transition-colors duration-150 focus-visible:ring-2 focus-visible:outline-none',\n category.emphasis ? 'text-destructive' : navLinkColor,\n isCurrent(category.href) && 'font-semibold underline underline-offset-4',\n )}\n >\n {category.label}\n </a>\n </li>\n ),\n )}\n </ul>\n </nav>\n\n <div className='flex items-center gap-1.5'>\n {showSearch ? (\n <>\n <div className='hidden lg:block lg:w-64'>\n <StorefrontNavbarSearchBar\n id='store-search'\n value={searchQuery}\n onValueChange={setSearchQuery}\n />\n </div>\n\n <Button\n ref={searchTriggerRef}\n variant='ghost'\n size='icon'\n className='lg:hidden'\n aria-label='Search products'\n aria-expanded={searchOpen}\n onClick={() => setSearchOpen(open => !open)}\n >\n {searchOpen ? <X /> : <Search />}\n </Button>\n </>\n ) : null}\n\n {accountUnavailable ? (\n <StorefrontNavbarAccountRetry pending={accountPending} onRetry={onAccountRetry} />\n ) : user ? (\n <StorefrontNavbarAccountMenu\n user={user}\n items={accountMenuItems}\n onHelp={onHelp}\n onSignOut={onSignOut}\n pending={accountPending}\n />\n ) : accountHref ? (\n accountPending ? (\n <Button variant='ghost' size='icon' className='size-11' disabled aria-label='Loading account session'>\n <UserRound aria-hidden='true' />\n </Button>\n ) : (\n <Button variant='ghost' size='icon' className='size-11' asChild>\n <a href={accountHref} aria-label='Account' aria-current={isCurrent(accountHref) ? 'page' : undefined}>\n <UserRound aria-hidden='true' />\n </a>\n </Button>\n )\n ) : null}\n\n <Sheet\n {...(cartOpen !== undefined ? { open: cartOpen, onOpenChange: onCartOpenChange } : {})}\n >\n <SheetTrigger asChild>\n <Button\n variant='ghost'\n size='icon'\n className='relative overflow-visible'\n aria-label={`Cart, ${count} ${count === 1 ? 'item' : 'items'}`}\n >\n <ShoppingBag className='size-5' />\n <CartBadge count={count} />\n </Button>\n </SheetTrigger>\n <SheetContent side='right' className='flex w-full max-w-sm flex-col gap-0 p-0'>\n <SheetHeader className='border-border border-b'>\n <SheetTitle className='text-left text-base'>\n Cart{count > 0 ? ` (${count})` : ''}\n </SheetTitle>\n </SheetHeader>\n <StorefrontNavbarCartSheet\n items={items}\n onQtyChange={changeQty}\n onRemove={removeItem}\n subtotal={subtotal}\n subtotalUnavailableLabel={subtotalUnavailableLabel}\n formatMoney={formatMoney}\n onCheckout={onCheckout}\n onViewCart={onViewCart}\n canonical={canonicalCart}\n state={cartState}\n errorLabel={cartErrorLabel}\n retryLabel={cartRetryLabel}\n onRetry={onCartRetry}\n checkoutUnavailable={checkoutUnavailable}\n checkoutDisabled={checkoutDisabled}\n viewCartUnavailable={viewCartUnavailable}\n />\n </SheetContent>\n </Sheet>\n </div>\n </div>\n\n <p aria-live='polite' className='sr-only'>\n {`Cart contains ${count} ${count === 1 ? 'item' : 'items'}`}\n </p>\n\n {showSearch && searchOpen ? (\n <div className='border-border flex flex-col gap-0 border-t p-4 lg:hidden'>\n <StorefrontNavbarSearchBar\n id='store-search-mobile'\n value={searchQuery}\n onValueChange={setSearchQuery}\n onDismiss={dismissSearch}\n />\n </div>\n ) : null}\n </header>\n )\n}\n\nexport default StorefrontNavbar\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/blocks/e-commerce/navigation/storefront-navbar.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react'\nimport { Menu, Search, ShoppingBag, UserRound, RotateCcw, X } from 'lucide-react'\n\nimport { Button } from '../../../ui/button'\nimport { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '../../../ui/sheet'\nimport { cn } from '../../../lib/utils'\nimport { MOTION } from '../../../lib/motion'\n\nimport { StorefrontNavbarAccountMenu, type AccountMenuItem, type StoreUser } from './storefront-navbar-account-menu'\nimport { StorefrontNavbarCartSheet, type CartItem, type CartSheetState } from './storefront-navbar-cart-sheet'\nimport type { UtilityLink } from './storefront-navbar-mobile-nav'\nimport { StorefrontNavbarSearchBar } from './storefront-navbar-search-bar'\nimport { MegaMenu } from './mega-menu'\nimport { MobileCategoryDrawer } from './mobile-category-drawer'\nimport type { MenuItem } from '../../../lib/types/menu'\nimport type { Money } from '@thorprovider/types'\nimport type { StoreCategory } from '../../../lib/contracts'\n\nfunction toMenuItem(category: StoreCategory): MenuItem {\n return {\n id: category.href,\n label: category.label,\n href: category.href,\n children: category.children?.map(toMenuItem),\n }\n}\n\n/**\n * Drawer entries come from three sources (categories, utility links, account\n * link). Hosts may reuse the same href across sources (e.g. a placeholder\n * href), which would produce duplicate React keys if passed through as-is.\n * Dedupe by href so every rendered item gets a unique id.\n */\nfunction uniqueById<T extends { id: string }>(items: T[]): T[] {\n const seen = new Set<string>()\n return items.filter((item) => {\n if (seen.has(item.id)) return false\n seen.add(item.id)\n return true\n })\n}\n\nexport interface LogoAccent {\n /** Trailing segment of `logoText` to render with the accent styling. */\n text: string\n /** Consumer-supplied classes for the accent span (e.g. a brand color token). */\n className?: string\n}\n\nfunction Logo({ text, href, accent }: { text: string; href?: string; accent?: LogoAccent }) {\n const className =\n 'focus-visible:ring-ring flex items-center gap-2 rounded-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none'\n\n const accentText = accent?.text ?? ''\n const hasAccent = accentText.length > 0 && text.endsWith(accentText)\n const baseText = hasAccent ? text.slice(0, text.length - accentText.length) : text\n\n const content = (\n <>\n <svg viewBox='0 0 32 32' aria-hidden='true' className='text-primary size-7' fill='none' xmlns='http://www.w3.org/2000/svg'>\n <path\n d='M26 24.75C26.4142 24.75 26.75 24.4142 26.75 24C26.75 23.5858 26.4142 23.25 26 23.25V24.75ZM26 23.25H11V24.75H26V23.25ZM8.75 21V15H7.25V21H8.75ZM11 23.25C9.75736 23.25 8.75 22.2426 8.75 21H7.25C7.25 23.0711 8.92893 24.75 11 24.75V23.25Z'\n fill='currentColor'\n />\n <path\n d='M1.5 3.25C1.08579 3.25 0.75 3.58579 0.75 4C0.75 4.41421 1.08579 4.75 1.5 4.75V3.25ZM1.5 4.75H6V3.25H1.5V4.75ZM7.25 6V21H8.75V6H7.25ZM6 4.75C6.69036 4.75 7.25 5.30964 7.25 6H8.75C8.75 4.48122 7.51878 3.25 6 3.25V4.75Z'\n fill='currentColor'\n />\n <path\n d='M22 21.75C22.4142 21.75 22.75 21.4142 22.75 21C22.75 20.5858 22.4142 20.25 22 20.25V21.75ZM22 20.25H11V21.75H22V20.25ZM8.75 18V12H7.25V18H8.75ZM11 20.25C9.75736 20.25 8.75 19.2426 8.75 18H7.25C7.25 20.0711 8.92893 21.75 11 21.75V20.25Z'\n fill='currentColor'\n />\n <path\n d='M27.2057 19.754C27.0654 20.1438 26.6357 20.346 26.246 20.2057C25.8562 20.0654 25.654 19.6357 25.7943 19.246L27.2057 19.754ZM30.0361 9.67744L29.3305 9.4234L29.3305 9.4234L30.0361 9.67744ZM25.7943 19.246L29.3305 9.4234L30.7418 9.93148L27.2057 19.754L25.7943 19.246ZM28.1543 7.75L8 7.75V6.25L28.1543 6.25V7.75ZM29.3305 9.4234C29.6237 8.60882 29.0201 7.75 28.1543 7.75V6.25C30.059 6.25 31.3869 8.13941 30.7418 9.93148L29.3305 9.4234Z'\n fill='currentColor'\n />\n <path\n d='M13.5 21.75C13.0858 21.75 12.75 21.4142 12.75 21C12.75 20.5858 13.0858 20.25 13.5 20.25V21.75ZM26.7111 19.009L27.4174 19.2613L27.4174 19.2613L26.7111 19.009ZM13.5 20.25H23.8858V21.75H13.5V20.25ZM26.0048 18.7568L27.7937 13.7477L29.2063 14.2523L27.4174 19.2613L26.0048 18.7568ZM23.8858 20.25C24.8367 20.25 25.6849 19.6522 26.0048 18.7568L27.4174 19.2613C26.8843 20.7537 25.4706 21.75 23.8858 21.75V20.25Z'\n fill='currentColor'\n />\n <path d='M21.1694 10.5806L14.5651 17.1849' stroke='currentColor' strokeWidth='1.5' strokeLinecap='round' />\n <path d='M22.1694 14.5806L18.5632 18.1868' stroke='currentColor' strokeWidth='1.5' strokeLinecap='round' />\n <circle cx='13.1' cy='26.1' r='1.7' stroke='currentColor' strokeWidth='1.2' />\n <circle cx='22.1' cy='26.1' r='1.7' stroke='currentColor' strokeWidth='1.2' />\n </svg>\n <span className='text-base font-semibold tracking-tight'>\n {baseText}\n {hasAccent ? <span className={accent?.className}>{accentText}</span> : null}\n </span>\n </>\n )\n\n if (!href) {\n return <span className={className}>{content}</span>\n }\n\n return (\n <a href={href} className={className}>\n {content}\n </a>\n )\n}\n\ntype CartBadgeProps = {\n count: number\n}\n\n/**\n * Transitions.dev `notification-badge`: diagonal slide + spring pop when the\n * count appears or changes. Positioned outside the bag so it never covers the icon.\n */\nfunction CartBadge({ count }: CartBadgeProps) {\n const reduceMotion = useReducedMotion()\n\n return (\n <AnimatePresence>\n {count > 0 ? (\n <motion.span\n key='badge-shell'\n className='bg-foreground text-background pointer-events-none absolute -top-2.5 -end-3.5 flex size-[1.125rem] items-center justify-center overflow-hidden rounded-full text-[10px] font-medium tabular-nums shadow-sm ring-2 ring-background'\n initial={\n reduceMotion\n ? false\n : {\n scale: 0,\n x: -MOTION.distancePx.feedback,\n y: MOTION.distancePx.state,\n opacity: 0,\n }\n }\n animate={{ scale: 1, x: 0, y: 0, opacity: 1 }}\n exit={\n reduceMotion\n ? { opacity: 0 }\n : {\n scale: 0,\n opacity: 0,\n transition: {\n duration: MOTION.durationSeconds.feedback,\n ease: MOTION.easing.standard,\n },\n }\n }\n transition={\n reduceMotion\n ? { duration: 0 }\n : {\n duration: MOTION.durationSeconds.state,\n ease: MOTION.easing.standard,\n }\n }\n style={{ willChange: 'transform, opacity' }}\n >\n <AnimatePresence mode='popLayout' initial={false}>\n <motion.span\n key={count}\n className='block'\n initial={reduceMotion ? false : { y: MOTION.distancePx.feedback, opacity: 0 }}\n animate={{ y: 0, opacity: 1 }}\n exit={\n reduceMotion\n ? undefined\n : { y: -MOTION.distancePx.feedback, opacity: 0 }\n }\n transition={{ duration: MOTION.durationSeconds.state, ease: MOTION.easing.standard }}\n >\n {count > 99 ? '99+' : count}\n </motion.span>\n </AnimatePresence>\n </motion.span>\n ) : null}\n </AnimatePresence>\n )\n}\n\nexport interface StorefrontNavbarAccountRetryProps {\n /** Consumer-owned reconciliation in flight; holds the affordance inert. */\n pending?: boolean\n /** Consumer-owned recovery action. Without it the affordance is inert. */\n onRetry?: () => void\n}\n\n/**\n * Recovery affordance for an unavailable session. The block never resolves the\n * session itself: it surfaces the state and dispatches the consumer's retry.\n * Extracted (hooks-free) so the dispatch is testable without a DOM.\n */\nexport function StorefrontNavbarAccountRetry({ pending = false, onRetry }: StorefrontNavbarAccountRetryProps) {\n return (\n <Button\n variant='ghost'\n size='icon'\n className='size-11'\n disabled={pending || !onRetry}\n aria-label='Retry account session'\n title='Account session unavailable'\n onClick={onRetry}\n >\n <RotateCcw aria-hidden='true' />\n </Button>\n )\n}\n\nexport interface StorefrontNavbarProps {\n storeCategories: StoreCategory[]\n /**\n * Optional note shown in the desktop utility strip. When omitted (or empty)\n * and there are no `utilityLinks`, the strip is not rendered at all, so a\n * block with no optional content paints no empty decorative chrome.\n */\n shippingNote?: string\n utilityLinks: UtilityLink[]\n logoText: string\n logoHref?: string\n /**\n * Optional accent for a trailing segment of `logoText` (e.g. the \"Cuba\" in\n * \"ElectroCuba\"). When omitted, or when `text` is not a trailing segment of\n * `logoText`, the wordmark renders unchanged.\n */\n logoAccent?: LogoAccent\n /** Account destination for anonymous shoppers on every viewport. */\n accountHref?: string\n /**\n * When `false`, no search control is rendered at all — neither the desktop\n * input, the mobile trigger, nor the mobile panel. Defaults to `true` so\n * legacy consumers keep the existing self-contained search. The generated\n * storefront passes `false` while no verified global search contract exists\n * (E2 task 5.4), so no global search is presented as working.\n */\n /**\n * The storefront's current route path. When it matches a destination the link\n * is marked as the current page (accessibly, beyond color alone).\n */\n currentPath?: string\n showSearch?: boolean\n searchQuery?: string\n onSearchChange?: (value: string) => void\n items?: CartItem[]\n /**\n * Quantity DELTA for a backend cart line-item id. The boundary converts the\n * delta into an absolute quantity against the authoritative current line\n * quantity before mutating the cart.\n */\n onQtyChange?: (id: string, delta: number) => void\n /** Remove the backend cart line-item id. */\n onRemove?: (id: string) => void\n /** Authoritative backend subtotal for the mini-cart. */\n subtotal?: Money\n /** Shown when an authoritative subtotal is supplied but absent/malformed. */\n subtotalUnavailableLabel?: string\n /** Override money formatting (locale, currency). Defaults to `Money.currencyCode`. */\n formatMoney?: (money: Money) => string\n user?: StoreUser\n accountMenuItems?: AccountMenuItem[]\n onHelp?: () => void\n onSignOut?: () => void\n accountPending?: boolean\n accountUnavailable?: boolean\n onAccountRetry?: () => void\n onCheckout?: () => void\n onViewCart?: () => void\n /**\n * Controlled visibility for the cart sheet. When provided, the sheet opens\n * and closes from this value and `onCartOpenChange` instead of internal\n * state, so a host can share one cart surface across the navbar trigger and\n * successful add-to-cart. Omit both to keep the legacy uncontrolled sheet.\n */\n cartOpen?: boolean\n /** Change handler paired with `cartOpen` for a controlled sheet. */\n onCartOpenChange?: (open: boolean) => void\n /**\n * Backend-authoritative cart rendering for the sheet. When `true`, line\n * amounts use each item's canonical `lineTotal` Money and never fall back to\n * numeric `price * qty`. Omit for the legacy numeric rendering.\n */\n canonicalCart?: boolean\n /** Cart read/mutation lifecycle for the sheet. */\n cartState?: CartSheetState\n /** Message shown when `cartState` is `error`. */\n cartErrorLabel?: string\n /** Recovery action label for the error state. */\n cartRetryLabel?: string\n /** Recovery action invoked from the error state. */\n onCartRetry?: () => void\n /** When `true`, the sheet's checkout action is suppressed (checkout not installed). */\n checkoutUnavailable?: boolean\n /** When `true`, the sheet's checkout action is disabled (cart not ready). */\n checkoutDisabled?: boolean\n /** When `true`, the sheet's review action is suppressed (cart view not installed). */\n viewCartUnavailable?: boolean\n /**\n * Consumer-supplied classes merged onto the outer `<header>` as the final\n * argument, so a semantic surface such as `bg-brand-nav\n * text-brand-nav-foreground` overrides the default `bg-background`. Purely\n * presentational: no layout, structure, or behavior changes.\n */\n className?: string\n}\n\nexport function StorefrontNavbar({\n storeCategories,\n shippingNote = '',\n utilityLinks,\n logoText,\n logoHref,\n logoAccent,\n accountHref,\n currentPath,\n showSearch = true,\n searchQuery: searchQueryProp,\n onSearchChange,\n items: itemsProp,\n onQtyChange: onQtyChangeProp,\n onRemove: onRemoveProp,\n subtotal,\n subtotalUnavailableLabel,\n formatMoney,\n user,\n accountMenuItems,\n onHelp,\n onSignOut,\n accountPending = false,\n accountUnavailable = false,\n onAccountRetry,\n onCheckout,\n onViewCart,\n cartOpen,\n onCartOpenChange,\n canonicalCart,\n cartState,\n cartErrorLabel,\n cartRetryLabel,\n onCartRetry,\n checkoutUnavailable,\n checkoutDisabled,\n viewCartUnavailable,\n className,\n}: StorefrontNavbarProps) {\n /**\n * Integration seam\n * ----------------\n * Pass cart + search from your storefront, or leave uncontrolled for a\n * self-contained demo. Controlled props win when provided.\n */\n const [internalItems, setInternalItems] = useState<CartItem[]>([])\n const [internalSearch, setInternalSearch] = useState('')\n const [searchOpen, setSearchOpen] = useState(false)\n const [menuOpen, setMenuOpen] = useState(false)\n const searchTriggerRef = useRef<HTMLButtonElement>(null)\n\n const items = itemsProp ?? internalItems\n const searchQuery = searchQueryProp ?? internalSearch\n\n const setSearchQuery = (value: string) => {\n onSearchChange?.(value)\n if (searchQueryProp === undefined) {\n setInternalSearch(value)\n }\n }\n\n const changeQty =\n onQtyChangeProp ??\n ((id: string, delta: number) =>\n setInternalItems(current =>\n current.flatMap(item => {\n if (item.id !== id) {\n return item\n }\n\n const qty = item.qty + delta\n return qty <= 0 ? [] : [{ ...item, qty }]\n }),\n ))\n\n const removeItem =\n onRemoveProp ?? ((id: string) => setInternalItems(current => current.filter(item => item.id !== id)))\n\n const count = useMemo(() => items.reduce((total, item) => total + item.qty, 0), [items])\n\n useEffect(() => {\n if (!showSearch || !searchOpen) {\n return\n }\n\n document.getElementById('store-search-mobile')?.focus()\n }, [searchOpen, showSearch])\n\n const dismissSearch = () => {\n setSearchOpen(false)\n searchTriggerRef.current?.focus()\n }\n\n // When the consumer overrides the header surface via `className`, the nav\n // links inherit its text color and need an explicit hover foreground so\n // `hover:bg-muted` never paints white-on-light; otherwise they keep the\n // default foreground (and the default hover surface).\n const navLinkColor =\n className !== undefined ? 'text-inherit hover:text-foreground' : 'text-foreground'\n // The current page is marked beyond color: an accessible current state plus a\n // visible weight/underline, and nothing when no destination matches.\n const isCurrent = (href?: string) => href !== undefined && href === currentPath\n\n // The desktop utility strip is decorative chrome: it is painted only when it\n // has content (a non-empty note or at least one utility link), never empty.\n const hasUtilityContent = shippingNote.trim().length > 0 || utilityLinks.length > 0\n\n return (\n <header\n className={cn(\n 'border-border sticky top-0 z-40 w-full border-b backdrop-blur-md',\n className ?? 'bg-background/95 supports-backdrop-filter:bg-background/80',\n )}\n >\n {hasUtilityContent ? (\n <div className='bg-foreground text-background hidden lg:block'>\n <div className='mx-auto flex h-9 w-full max-w-7xl items-center justify-between px-4 text-xs tracking-wide sm:px-6 lg:px-8'>\n <p className='text-background/80'>{shippingNote}</p>\n <ul className='flex items-center gap-5'>\n {utilityLinks.map(link => (\n <li key={`${link.href}:${link.label}`}>\n <a\n href={link.href}\n className='text-background/80 hover:text-background transition-colors duration-150'\n >\n {link.label}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n ) : null}\n\n <div className='mx-auto flex h-16 w-full max-w-7xl items-center gap-3 px-4 sm:px-6 lg:px-8'>\n <Button\n variant='ghost'\n size='icon'\n className='lg:hidden'\n aria-label='Open menu'\n aria-expanded={menuOpen}\n onClick={() => setMenuOpen(open => !open)}\n >\n <Menu />\n </Button>\n\n <MobileCategoryDrawer\n categories={uniqueById([\n ...storeCategories.map(toMenuItem),\n ...utilityLinks.map(link => ({ id: link.href, label: link.label, href: link.href })),\n ...(accountHref ? [{ id: accountHref, label: 'Account', href: accountHref }] : []),\n ])}\n collections={[]}\n open={menuOpen}\n onClose={() => setMenuOpen(false)}\n viewAllHref=''\n />\n\n <div className='flex-1 lg:flex-none'>\n <Logo text={logoText} href={logoHref} accent={logoAccent} />\n </div>\n\n <nav aria-label='Store' className='hidden flex-1 lg:block'>\n <ul className='flex items-center gap-0.5'>\n {storeCategories.map(category =>\n category.children && category.children.length > 0 ? (\n <li key={category.href} className='group relative'>\n <a\n href={category.href}\n aria-current={isCurrent(category.href) ? 'page' : undefined}\n className={cn(\n 'hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-2 text-sm font-medium transition-colors duration-150 focus-visible:ring-2 focus-visible:outline-none',\n category.emphasis ? 'text-destructive' : navLinkColor,\n isCurrent(category.href) && 'font-semibold underline underline-offset-4',\n )}\n >\n {category.label}\n </a>\n <div className='invisible absolute left-0 top-full z-50 pt-2 opacity-0 transition-opacity duration-150 group-hover:visible group-hover:opacity-100'>\n <MegaMenu\n categories={[toMenuItem(category)]}\n collections={[]}\n collectionsHref=''\n categoryColumnTitle={category.label}\n />\n </div>\n </li>\n ) : (\n <li key={category.href}>\n <a\n href={category.href}\n aria-current={isCurrent(category.href) ? 'page' : undefined}\n className={cn(\n 'hover:bg-muted focus-visible:ring-ring rounded-md px-3 py-2 text-sm font-medium transition-colors duration-150 focus-visible:ring-2 focus-visible:outline-none',\n category.emphasis ? 'text-destructive' : navLinkColor,\n isCurrent(category.href) && 'font-semibold underline underline-offset-4',\n )}\n >\n {category.label}\n </a>\n </li>\n ),\n )}\n </ul>\n </nav>\n\n <div className='flex items-center gap-1.5'>\n {showSearch ? (\n <>\n <div className='hidden lg:block lg:w-64'>\n <StorefrontNavbarSearchBar\n id='store-search'\n value={searchQuery}\n onValueChange={setSearchQuery}\n />\n </div>\n\n <Button\n ref={searchTriggerRef}\n variant='ghost'\n size='icon'\n className='lg:hidden'\n aria-label='Search products'\n aria-expanded={searchOpen}\n onClick={() => setSearchOpen(open => !open)}\n >\n {searchOpen ? <X /> : <Search />}\n </Button>\n </>\n ) : null}\n\n {accountUnavailable ? (\n <StorefrontNavbarAccountRetry pending={accountPending} onRetry={onAccountRetry} />\n ) : user ? (\n <StorefrontNavbarAccountMenu\n user={user}\n items={accountMenuItems}\n onHelp={onHelp}\n onSignOut={onSignOut}\n pending={accountPending}\n />\n ) : accountHref ? (\n accountPending ? (\n <Button variant='ghost' size='icon' className='size-11' disabled aria-label='Loading account session'>\n <UserRound aria-hidden='true' />\n </Button>\n ) : (\n <Button variant='ghost' size='icon' className='size-11' asChild>\n <a href={accountHref} aria-label='Account' aria-current={isCurrent(accountHref) ? 'page' : undefined}>\n <UserRound aria-hidden='true' />\n </a>\n </Button>\n )\n ) : null}\n\n <Sheet\n {...(cartOpen !== undefined ? { open: cartOpen, onOpenChange: onCartOpenChange } : {})}\n >\n <SheetTrigger asChild>\n <Button\n variant='ghost'\n size='icon'\n className='relative overflow-visible'\n aria-label={`Cart, ${count} ${count === 1 ? 'item' : 'items'}`}\n >\n <ShoppingBag className='size-5' />\n <CartBadge count={count} />\n </Button>\n </SheetTrigger>\n <SheetContent side='right' className='flex w-full max-w-sm flex-col gap-0 p-0'>\n <SheetHeader className='border-border border-b'>\n <SheetTitle className='text-left text-base'>\n Cart{count > 0 ? ` (${count})` : ''}\n </SheetTitle>\n </SheetHeader>\n <StorefrontNavbarCartSheet\n items={items}\n onQtyChange={changeQty}\n onRemove={removeItem}\n subtotal={subtotal}\n subtotalUnavailableLabel={subtotalUnavailableLabel}\n formatMoney={formatMoney}\n onCheckout={onCheckout}\n onViewCart={onViewCart}\n canonical={canonicalCart}\n state={cartState}\n errorLabel={cartErrorLabel}\n retryLabel={cartRetryLabel}\n onRetry={onCartRetry}\n checkoutUnavailable={checkoutUnavailable}\n checkoutDisabled={checkoutDisabled}\n viewCartUnavailable={viewCartUnavailable}\n />\n </SheetContent>\n </Sheet>\n </div>\n </div>\n\n <p aria-live='polite' className='sr-only'>\n {`Cart contains ${count} ${count === 1 ? 'item' : 'items'}`}\n </p>\n\n {showSearch && searchOpen ? (\n <div className='border-border flex flex-col gap-0 border-t p-4 lg:hidden'>\n <StorefrontNavbarSearchBar\n id='store-search-mobile'\n value={searchQuery}\n onValueChange={setSearchQuery}\n onDismiss={dismissSearch}\n />\n </div>\n ) : null}\n </header>\n )\n}\n\nexport default StorefrontNavbar\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-card.d.ts","sourceRoot":"","sources":["../../../../src/blocks/e-commerce/product-list/product-card.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"product-card.d.ts","sourceRoot":"","sources":["../../../../src/blocks/e-commerce/product-list/product-card.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAEvF;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,WAAW,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC,CAAA;AAEvF,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,IAAI,EAAE,mBAAmB,CAAA;IACzB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,uBAAuB,CAAA;IACtC,+EAA+E;IAC/E,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAA;IACjD;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAA;IACpD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,EAAE,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IAC1E,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAA;IACnD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,2EAA2E;IAC3E,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAiYD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,YAAwB,EACxB,UAAU,EACV,aAAa,EACb,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAqC,EACrC,qBAA8C,EAC9C,kBAAyC,EACzC,uBAA+C,EAC/C,gBAAkC,GACnC,EAAE,gBAAgB,+BAoBlB;AAED,eAAe,WAAW,CAAA"}
|