@mohasinac/appkit 4.53.2 → 4.54.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/dist/.build-stamp.json +3 -3
- package/dist/_internal/server/features/auth/capabilities.js +7 -5
- package/dist/_internal/server/features/checkout/actions.d.ts +22 -6
- package/dist/_internal/server/features/checkout/actions.js +96 -51
- package/dist/_internal/server/features/checkout/index.d.ts +1 -1
- package/dist/_internal/server/features/checkout/index.js +1 -1
- package/dist/_internal/server/features/checkout/supplier-identity.js +28 -6
- package/dist/_internal/server/features/orders/adapters.js +1 -3
- package/dist/_internal/server/features/products/listing-tab-counts.js +81 -25
- package/dist/_internal/server/features/search/index-build/sources.js +43 -2
- package/dist/_internal/server/features/site-settings/adapters.js +1 -1
- package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
- package/dist/_internal/server/features/stores/adapters.js +0 -1
- package/dist/_internal/server/jobs/core/analyticsAlertEvaluate.js +2 -5
- package/dist/_internal/server/jobs/core/jobRunners.js +0 -10
- package/dist/_internal/server/jobs/core/onOrderCreate.js +10 -104
- package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +0 -2
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +0 -1
- package/dist/_internal/server/jobs/core/onScamReportCreate.js +0 -1
- package/dist/_internal/server/jobs/core/onScamReportRejected.js +0 -1
- package/dist/_internal/server/jobs/core/onScamReportVerified.js +0 -1
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +0 -1
- package/dist/_internal/server/jobs/core/pendingOrderTimeout.js +0 -1
- package/dist/_internal/server/notifications/channel-health.d.ts +7 -3
- package/dist/_internal/server/notifications/channel-health.js +2 -2
- package/dist/_internal/server/notifications/send-guard.d.ts +1 -1
- package/dist/_internal/server/notifications/send-guard.js +2 -4
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +128 -28
- package/dist/_internal/shared/checkout/order-math.d.ts +1 -1
- package/dist/_internal/shared/checkout/order-math.js +1 -1
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +1 -1
- package/dist/_internal/shared/features/checkout/config.d.ts +0 -2
- package/dist/_internal/shared/features/checkout/config.js +0 -2
- package/dist/_internal/shared/features/messaging/config.d.ts +7 -5
- package/dist/_internal/shared/features/messaging/config.js +1 -4
- package/dist/_internal/shared/features/site-settings/fees.d.ts +0 -2
- package/dist/_internal/shared/features/site-settings/fees.js +0 -2
- package/dist/_internal/shared/features/site-settings/supplier-of-record.d.ts +56 -0
- package/dist/_internal/shared/features/site-settings/supplier-of-record.js +57 -0
- package/dist/_internal/shared/fees/calculator.d.ts +0 -8
- package/dist/_internal/shared/fees/calculator.js +0 -7
- package/dist/_internal/shared/listing-types/tiers.d.ts +94 -0
- package/dist/_internal/shared/listing-types/tiers.js +150 -0
- package/dist/cli/index.js +0 -2
- package/dist/client.d.ts +25 -4
- package/dist/client.js +36 -5
- package/dist/constants/api-endpoints.d.ts +21 -15
- package/dist/constants/api-endpoints.js +7 -8
- package/dist/constants/field-names.d.ts +1 -0
- package/dist/constants/field-names.js +1 -0
- package/dist/constants/notification-types.d.ts +1 -1
- package/dist/constants/notification-types.js +1 -1
- package/dist/core/integration-keys.d.ts +5 -5
- package/dist/core/integration-keys.js +21 -10
- package/dist/features/about/components/FeesView.js +0 -6
- package/dist/features/about/components/GuidesHubView.js +15 -2
- package/dist/features/account/components/NotificationPreferencesPanel.js +3 -4
- package/dist/features/account/components/UserOrdersView.js +26 -7
- package/dist/features/account/types/index.d.ts +0 -2
- package/dist/features/addresses/utils/postal-autofill.d.ts +39 -0
- package/dist/features/addresses/utils/postal-autofill.js +54 -0
- package/dist/features/admin/actions/notification-actions.d.ts +2 -8
- package/dist/features/admin/actions/notification-actions.js +9 -104
- package/dist/features/admin/components/AdminGuideHubView.js +1 -8
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +1 -1
- package/dist/features/admin/components/AdminOrdersView.js +0 -2
- package/dist/features/admin/components/AdminSectionsView.js +3 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +22 -68
- package/dist/features/admin/components/AdminStoreEditorView.js +72 -34
- package/dist/features/admin/components/OwnerQuickActions.d.ts +29 -0
- package/dist/features/admin/components/OwnerQuickActions.js +142 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.js +13 -4
- package/dist/features/admin/components/sections/icon-options.d.ts +21 -0
- package/dist/features/admin/components/sections/icon-options.js +23 -0
- package/dist/features/admin/components/sections/sectionTemplates.js +4 -1
- package/dist/features/admin/constants/site-settings-tabs.d.ts +7 -12
- package/dist/features/admin/constants/site-settings-tabs.js +6 -12
- package/dist/features/admin/repository/site-settings.repository.js +1 -1
- package/dist/features/admin/schemas/admin-editor-forms.d.ts +1 -1
- package/dist/features/admin/schemas/admin-editor-forms.js +4 -1
- package/dist/features/admin/schemas/admin-user-form.d.ts +0 -61
- package/dist/features/admin/schemas/admin-user-form.js +3 -44
- package/dist/features/admin/schemas/firestore.d.ts +28 -54
- package/dist/features/admin/schemas/firestore.js +40 -18
- package/dist/features/auctions/components/AuctionDetailPageView.js +4 -3
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -2
- package/dist/features/auth/checkout-value-otp.d.ts +1 -1
- package/dist/features/auth/checkout-value-otp.js +1 -1
- package/dist/features/auth/permissions/constants.d.ts +29 -2
- package/dist/features/auth/permissions/constants.js +67 -1
- package/dist/features/blog/components/BlogFeaturedCard.d.ts +11 -1
- package/dist/features/blog/components/BlogFeaturedCard.js +9 -2
- package/dist/features/cart/components/CartDrawer.js +3 -2
- package/dist/features/cart/components/CartGroupLineRow.js +2 -1
- package/dist/features/cart/components/CartPriceBreakdown.d.ts +0 -2
- package/dist/features/cart/components/CartPriceBreakdown.js +1 -1
- package/dist/features/cart/components/StoreAddonsPicker.d.ts +2 -5
- package/dist/features/cart/components/StoreAddonsPicker.js +4 -5
- package/dist/features/cart/hooks/useAddToCart.js +10 -5
- package/dist/features/cart/repository/cart.repository.js +1 -2
- package/dist/features/cart/schemas/firestore.d.ts +1 -2
- package/dist/features/cart/utils/pending-ops.d.ts +11 -1
- package/dist/features/cart/utils/pending-ops.js +14 -2
- package/dist/features/categories/components/BrandDetailPageView.js +2 -1
- package/dist/features/categories/components/BundleDetailView.js +2 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +2 -1
- package/dist/features/categories/components/CategoryGrid.d.ts +11 -1
- package/dist/features/categories/components/CategoryGrid.js +9 -2
- package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +10 -5
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +2 -88
- package/dist/features/classified/components/ClassifiedDetailPageView.js +2 -1
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +2 -1
- package/dist/features/events/components/EventCard.d.ts +11 -1
- package/dist/features/events/components/EventCard.js +9 -2
- package/dist/features/grouped/components/GroupedListingDetailView.js +3 -1
- package/dist/features/homepage/components/CTABannerSection.d.ts +3 -1
- package/dist/features/homepage/components/CTABannerSection.js +6 -3
- package/dist/features/homepage/components/HeroCarousel.js +8 -6
- package/dist/features/homepage/components/MarketplaceHomepageView.js +33 -7
- package/dist/features/homepage/components/SectionCarousel.js +13 -5
- package/dist/features/homepage/components/SecurityHighlightsSection.d.ts +8 -3
- package/dist/features/homepage/components/SecurityHighlightsSection.js +2 -2
- package/dist/features/homepage/components/StatsCounterSection.d.ts +9 -4
- package/dist/features/homepage/components/StatsCounterSection.js +2 -2
- package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
- package/dist/features/homepage/components/TrustFeaturesSection.d.ts +18 -4
- package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
- package/dist/features/homepage/components/WelcomeSection.d.ts +13 -2
- package/dist/features/homepage/components/WelcomeSection.js +3 -3
- package/dist/features/homepage/components/WhatsAppCommunitySection.d.ts +28 -0
- package/dist/features/homepage/components/WhatsAppCommunitySection.js +42 -6
- package/dist/features/homepage/components/WhatsAppGlyph.d.ts +20 -0
- package/dist/features/homepage/components/WhatsAppGlyph.js +20 -0
- package/dist/features/homepage/constants/hero-carousel-styles.d.ts +8 -6
- package/dist/features/homepage/constants/hero-carousel-styles.js +8 -6
- package/dist/features/homepage/constants/section-copy.d.ts +12 -10
- package/dist/features/homepage/constants/section-copy.js +28 -6
- package/dist/features/homepage/constants/stat-icons.d.ts +12 -0
- package/dist/features/homepage/constants/stat-icons.js +17 -0
- package/dist/features/homepage/constants/trust-icon-aliases.d.ts +8 -0
- package/dist/features/homepage/constants/trust-icon-aliases.js +75 -0
- package/dist/features/homepage/lib/section-defaults.d.ts +16 -1
- package/dist/features/homepage/lib/section-defaults.js +24 -4
- package/dist/features/homepage/lib/section-renderer.js +48 -8
- package/dist/features/homepage/schemas/firestore.d.ts +18 -1
- package/dist/features/layout/AppLayoutShell.js +2 -1
- package/dist/features/layout/BottomActions.d.ts +1 -0
- package/dist/features/layout/BottomActions.js +330 -0
- package/dist/features/layout/BottomChrome.d.ts +45 -0
- package/dist/features/layout/BottomChrome.js +5 -17
- package/dist/features/layout/SideActionDock.js +36 -13
- package/dist/features/layout/index.d.ts +2 -7
- package/dist/features/layout/index.js +7 -7
- package/dist/features/layout/useIsDesktop.d.ts +36 -0
- package/dist/features/layout/useIsDesktop.js +48 -0
- package/dist/features/live/components/LiveItemDetailPageView.js +2 -1
- package/dist/features/orders/actions/refund-actions.js +0 -1
- package/dist/features/orders/components/OrderAddonBadges.d.ts +1 -3
- package/dist/features/orders/components/OrderAddonBadges.js +3 -4
- package/dist/features/orders/components/OrderPaymentSummary.js +15 -2
- package/dist/features/orders/components/YourPurchaseStrip.d.ts +24 -0
- package/dist/features/orders/components/YourPurchaseStrip.js +77 -0
- package/dist/features/orders/components/index.d.ts +2 -1
- package/dist/features/orders/components/index.js +1 -1
- package/dist/features/orders/repository/orders.repository.d.ts +0 -8
- package/dist/features/orders/repository/orders.repository.js +0 -2
- package/dist/features/orders/schemas/firestore.d.ts +17 -9
- package/dist/features/orders/types/index.d.ts +2 -5
- package/dist/features/orders/utils/order-announcement-message.d.ts +18 -0
- package/dist/features/orders/utils/order-announcement-message.js +16 -0
- package/dist/features/orders/utils/payment-proof-message.d.ts +20 -0
- package/dist/features/orders/utils/payment-proof-message.js +17 -0
- package/dist/features/parts/components/PartDetailPageView.js +96 -1
- package/dist/features/parts/schemas/firestore.d.ts +247 -0
- package/dist/features/parts/schemas/firestore.js +6 -6
- package/dist/features/pre-orders/components/MarketplacePreorderCard.d.ts +11 -1
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +10 -3
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -3
- package/dist/features/products/api/[id]/route.js +8 -1
- package/dist/features/products/api/route.js +16 -4
- package/dist/features/products/components/AvailabilityScopeHint.js +1 -1
- package/dist/features/products/components/InteractiveProductCard.d.ts +7 -1
- package/dist/features/products/components/InteractiveProductCard.js +16 -4
- package/dist/features/products/components/MarketplaceBundleCard.d.ts +11 -1
- package/dist/features/products/components/MarketplaceBundleCard.js +9 -2
- package/dist/features/products/components/MarketplacePrizeDrawCard.d.ts +11 -1
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +9 -2
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -1
- package/dist/features/products/components/ProductDetailPageView.js +27 -2
- package/dist/features/products/components/ProductGrid.d.ts +14 -1
- package/dist/features/products/components/ProductGrid.js +22 -5
- package/dist/features/products/components/ProductsIndexListing.js +2 -2
- package/dist/features/reviews/api/[id]/route.js +83 -23
- package/dist/features/reviews/components/PurchaseReviewAffordance.d.ts +6 -0
- package/dist/features/reviews/components/PurchaseReviewAffordance.js +42 -0
- package/dist/features/reviews/components/ReviewFormDrawer.d.ts +34 -0
- package/dist/features/reviews/components/ReviewFormDrawer.js +127 -0
- package/dist/features/reviews/components/index.d.ts +4 -0
- package/dist/features/reviews/components/index.js +2 -0
- package/dist/features/scams/schemas/index.d.ts +10 -10
- package/dist/features/search/action-index/settings-entries.js +0 -9
- package/dist/features/seller/actions/seller-actions.d.ts +1 -1
- package/dist/features/seller/actions/seller-actions.js +49 -3
- package/dist/features/seller/components/SellerPayoutSettingsView.js +30 -2
- package/dist/features/seller/components/SellerProductShell.d.ts +17 -1
- package/dist/features/seller/hooks/useStoreListingEntitlements.d.ts +8 -0
- package/dist/features/seller/hooks/useStoreListingEntitlements.js +70 -0
- package/dist/features/store-extensions/repository/store-extensions.repositories.d.ts +1 -6
- package/dist/features/store-extensions/repository/store-extensions.repositories.js +1 -10
- package/dist/features/store-extensions/schemas/firestore.d.ts +1 -17
- package/dist/features/store-extensions/schemas/firestore.js +0 -10
- package/dist/features/stores/components/InteractiveStoreCard.d.ts +11 -1
- package/dist/features/stores/components/InteractiveStoreCard.js +9 -2
- package/dist/features/stores/components/StoreCapabilitiesGuideView.js +0 -1
- package/dist/features/stores/components/StoreGuideHubView.js +2 -8
- package/dist/features/stores/components/StoreSettingsGuideView.js +2 -6
- package/dist/features/stores/components/index.d.ts +0 -2
- package/dist/features/stores/components/index.js +0 -1
- package/dist/features/stores/repository/store.repository.d.ts +1 -26
- package/dist/features/stores/repository/store.repository.js +5 -60
- package/dist/features/stores/schemas/firestore.d.ts +6 -25
- package/dist/features/stores/schemas/firestore.js +6 -3
- package/dist/features/stores/schemas/index.d.ts +1 -87
- package/dist/features/stores/schemas/index.js +10 -15
- package/dist/features/tester/seed-data/authored/admin__site-system.js +0 -48
- package/dist/features/tester/seed-data/authored/buying__buying-checkout.js +0 -40
- package/dist/features/tester/seed-data/authored/selling__quick-add-minimum-details.js +0 -16
- package/dist/features/tester/seed-data/authored/selling__seller-guide.js +1 -1
- package/dist/features/tester/seed-data/authored/selling__seller-marketing-extras.js +0 -79
- package/dist/features/tester/seed-data/authored/selling__seller-orders.js +1 -1
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +415 -69
- package/dist/index.d.ts +20 -32
- package/dist/index.js +34 -43
- package/dist/next/routing/route-map.d.ts +2 -8
- package/dist/next/routing/route-map.js +21 -4
- package/dist/providers/db-firebase/base.repository.d.ts +1 -1
- package/dist/providers/db-firebase/base.repository.js +1 -1
- package/dist/providers/payment-razorpay/index.d.ts +125 -0
- package/dist/providers/payment-razorpay/index.js +232 -0
- package/dist/providers/payment-razorpay/signature.d.ts +53 -0
- package/dist/providers/payment-razorpay/signature.js +71 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +98 -0
- package/dist/providers/shipping-shiprocket/index.js +356 -0
- package/dist/providers.d.ts +3 -0
- package/dist/providers.js +3 -0
- package/dist/react/hooks/useCanSeePrices.d.ts +0 -27
- package/dist/react/hooks/useCanSeePrices.js +25 -0
- package/dist/repositories/index.d.ts +1 -1
- package/dist/repositories/index.js +1 -1
- package/dist/schemas/registry.d.ts +10 -115
- package/dist/schemas/registry.js +1 -2
- package/dist/security/pii-encrypt.js +1 -1
- package/dist/seed/_helpers/category-forest.js +27 -0
- package/dist/seed/_helpers/category-parts-glossary-map.js +1816 -86
- package/dist/seed/_helpers/category-parts.d.ts +1 -1
- package/dist/seed/_helpers/category-parts.js +13412 -3020
- package/dist/seed/carousel-slides-seed-data.js +47 -10
- package/dist/seed/categories-seed-data.js +48 -6
- package/dist/seed/faq-seed-data.js +2 -2
- package/dist/seed/homepage-sections-seed-data.js +286 -54
- package/dist/seed/index.d.ts +1 -1
- package/dist/seed/index.js +1 -1
- package/dist/seed/manifest.d.ts +1 -1
- package/dist/seed/manifest.js +1 -2
- package/dist/seed/model-composition-seed-data.js +6 -8
- package/dist/seed/part-glossary/chunk0.d.ts +9 -0
- package/dist/seed/part-glossary/chunk0.js +35448 -0
- package/dist/seed/part-glossary/chunk1.d.ts +9 -0
- package/dist/seed/part-glossary/chunk1.js +40494 -0
- package/dist/seed/part-glossary/chunk2.d.ts +9 -0
- package/dist/seed/part-glossary/chunk2.js +51242 -0
- package/dist/seed/part-glossary/chunk3.d.ts +9 -0
- package/dist/seed/part-glossary/chunk3.js +53337 -0
- package/dist/seed/part-glossary/chunk4.d.ts +9 -0
- package/dist/seed/part-glossary/chunk4.js +51454 -0
- package/dist/seed/part-glossary-seed-data.d.ts +1 -1
- package/dist/seed/part-glossary-seed-data.js +23 -47483
- package/dist/seed/site-settings-seed-data.js +34 -35
- package/dist/seed/store-extensions-seed-data.d.ts +1 -2
- package/dist/seed/store-extensions-seed-data.js +1 -23
- package/dist/seed/stores-seed-data.js +0 -1
- package/dist/server-entry.d.ts +1 -1
- package/dist/server-entry.js +1 -1
- package/dist/server.d.ts +8 -10
- package/dist/server.js +16 -22
- package/dist/styles.css +392 -43
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +1 -1
- package/dist/tokens/themes/default-light.js +2 -1
- package/dist/tokens/tokens.css +6 -2
- package/dist/ui/components/Button.d.ts +11 -0
- package/dist/ui/components/Button.js +11 -0
- package/dist/ui/components/Button.style.css +29 -0
- package/dist/ui/components/CarouselNav.d.ts +57 -0
- package/dist/ui/components/CarouselNav.js +25 -0
- package/dist/ui/components/CarouselNav.style.css +265 -0
- package/dist/ui/components/GatedPrice.js +30 -3
- package/dist/ui/components/GatedPrice.style.css +43 -40
- package/dist/ui/components/HorizontalScroller.d.ts +12 -1
- package/dist/ui/components/HorizontalScroller.js +43 -3
- package/dist/ui/components/ImageMosaic.d.ts +8 -1
- package/dist/ui/components/ImageMosaic.js +3 -2
- package/dist/ui/components/ImageMosaic.style.css +22 -0
- package/dist/ui/components/Layout.style.css +6 -0
- package/dist/ui/components/Semantic.d.ts +3 -2
- package/dist/ui/components/Semantic.js +1 -0
- package/dist/ui/components/Typography.d.ts +2 -0
- package/dist/ui/components/Typography.js +2 -0
- package/dist/ui/components/Typography.style.css +19 -0
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/index.d.ts +3 -1
- package/dist/ui/index.js +4 -0
- package/package.json +3 -2
- package/dist/_internal/server/jobs/core/whatsappCatalogImport.d.ts +0 -27
- package/dist/_internal/server/jobs/core/whatsappCatalogImport.js +0 -172
- package/dist/_internal/server/jobs/core/whatsappNotify.d.ts +0 -35
- package/dist/_internal/server/jobs/core/whatsappNotify.js +0 -140
- package/dist/features/admin/components/AdminWhatsAppGuideView.d.ts +0 -2
- package/dist/features/admin/components/AdminWhatsAppGuideView.js +0 -35
- package/dist/features/orders/components/MarketplaceOrderCard.d.ts +0 -36
- package/dist/features/orders/components/MarketplaceOrderCard.js +0 -57
- package/dist/features/stores/components/StoreWhatsAppGuideView.d.ts +0 -3
- package/dist/features/stores/components/StoreWhatsAppGuideView.js +0 -12
- package/dist/features/whatsapp-bot/api/send-status/route.d.ts +0 -12
- package/dist/features/whatsapp-bot/api/send-status/route.js +0 -38
- package/dist/features/whatsapp-bot/api/webhook/route.d.ts +0 -12
- package/dist/features/whatsapp-bot/api/webhook/route.js +0 -43
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.d.ts +0 -6
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +0 -270
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.d.ts +0 -9
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +0 -7
- package/dist/features/whatsapp-bot/components/index.d.ts +0 -3
- package/dist/features/whatsapp-bot/components/index.js +0 -2
- package/dist/features/whatsapp-bot/helpers/payment-proof-message.d.ts +0 -14
- package/dist/features/whatsapp-bot/helpers/payment-proof-message.js +0 -17
- package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +0 -52
- package/dist/features/whatsapp-bot/helpers/whatsapp.js +0 -283
- package/dist/features/whatsapp-bot/index.d.ts +0 -3
- package/dist/features/whatsapp-bot/index.js +0 -3
- package/dist/features/whatsapp-bot/manifest.d.ts +0 -2
- package/dist/features/whatsapp-bot/manifest.js +0 -13
- package/dist/features/whatsapp-bot/messages/en.json +0 -7
- package/dist/features/whatsapp-bot/server.d.ts +0 -7
- package/dist/features/whatsapp-bot/server.js +0 -7
- package/dist/features/whatsapp-bot/types/index.d.ts +0 -126
- package/dist/features/whatsapp-bot/types/index.js +0 -1
|
@@ -110,7 +110,7 @@ export const DEFAULT_DARK_THEME = {
|
|
|
110
110
|
"accent-banner": "linear-gradient(to right, var(--appkit-color-primary), var(--appkit-color-secondary))",
|
|
111
111
|
promotion: "linear-gradient(to bottom right, var(--appkit-color-error), var(--appkit-color-primary), var(--appkit-color-warning))",
|
|
112
112
|
spotlight: "linear-gradient(to bottom right, rgba(6,182,212,0.10), var(--appkit-color-bg), rgba(6,182,212,0.10))",
|
|
113
|
-
"whatsapp-card": "linear-gradient(
|
|
113
|
+
"whatsapp-card": "linear-gradient(135deg, var(--appkit-color-whatsapp) 0%, var(--appkit-color-whatsapp-light) 48%, var(--appkit-color-whatsapp-dark) 100%)",
|
|
114
114
|
glass: "linear-gradient(to bottom right, color-mix(in srgb, var(--appkit-color-surface) 85%, transparent), color-mix(in srgb, var(--appkit-color-surface) 65%, transparent))",
|
|
115
115
|
"card-indigo": "linear-gradient(to bottom right, rgba(239,68,68,0.10), var(--appkit-color-surface), var(--appkit-color-surface))",
|
|
116
116
|
"card-teal": "linear-gradient(to bottom right, rgba(6,182,212,0.10), var(--appkit-color-surface), var(--appkit-color-surface))",
|
|
@@ -68,6 +68,7 @@ export const DEFAULT_LIGHT_THEME = {
|
|
|
68
68
|
"appkit-color-star": "#facc15",
|
|
69
69
|
"appkit-color-whatsapp-light": "#1ebe5d",
|
|
70
70
|
"appkit-color-whatsapp-bg": "#ECE5DD",
|
|
71
|
+
"appkit-color-whatsapp-dark": "#075E54",
|
|
71
72
|
"appkit-color-focus-ring": "#0d9488",
|
|
72
73
|
"appkit-shadow-glow": "0 0 0 1px rgba(13,148,136,0.10), 0 4px 16px -4px rgba(13,148,136,0.20)",
|
|
73
74
|
"appkit-shadow-glow-pink": "0 0 0 1px rgba(192,38,211,0.12), 0 4px 16px -4px rgba(192,38,211,0.22)",
|
|
@@ -116,7 +117,7 @@ export const DEFAULT_LIGHT_THEME = {
|
|
|
116
117
|
"accent-banner": "linear-gradient(to right, var(--appkit-color-primary), var(--appkit-color-secondary))",
|
|
117
118
|
promotion: "linear-gradient(to bottom right, var(--appkit-color-error), var(--appkit-color-primary), var(--appkit-color-warning))",
|
|
118
119
|
spotlight: "linear-gradient(to bottom right, var(--appkit-color-info-surface), var(--appkit-color-bg), var(--appkit-color-info-surface))",
|
|
119
|
-
"whatsapp-card": "linear-gradient(
|
|
120
|
+
"whatsapp-card": "linear-gradient(135deg, var(--appkit-color-whatsapp) 0%, var(--appkit-color-whatsapp-light) 48%, var(--appkit-color-whatsapp-dark) 100%)",
|
|
120
121
|
glass: "linear-gradient(to bottom right, color-mix(in srgb, var(--appkit-color-surface) 85%, transparent), color-mix(in srgb, var(--appkit-color-surface) 65%, transparent))",
|
|
121
122
|
"card-indigo": "linear-gradient(to bottom right, var(--appkit-color-primary-50), var(--appkit-color-surface), var(--appkit-color-surface))",
|
|
122
123
|
"card-teal": "linear-gradient(to bottom right, var(--appkit-color-secondary-50), var(--appkit-color-surface), var(--appkit-color-surface))",
|
package/dist/tokens/tokens.css
CHANGED
|
@@ -217,6 +217,10 @@
|
|
|
217
217
|
--appkit-color-whatsapp: #25D366;
|
|
218
218
|
--appkit-color-whatsapp-light: #1ebe5d;
|
|
219
219
|
--appkit-color-whatsapp-bg: #ECE5DD;
|
|
220
|
+
/* WhatsApp's own deep teal. Needed as a third gradient stop: a green
|
|
221
|
+
darkened with color-mix() reads olive, not teal, so the brand's dark end
|
|
222
|
+
cannot be derived from --appkit-color-whatsapp. */
|
|
223
|
+
--appkit-color-whatsapp-dark: #075E54;
|
|
220
224
|
--appkit-color-youtube: #FF0000;
|
|
221
225
|
--appkit-gradient-instagram: linear-gradient(to bottom right, #a855f7, #ec4899, #fb923c);
|
|
222
226
|
}
|
|
@@ -346,7 +350,7 @@
|
|
|
346
350
|
--appkit-gradient-accent-banner: linear-gradient(to right, var(--appkit-color-primary), var(--appkit-color-secondary));
|
|
347
351
|
--appkit-gradient-promotion: linear-gradient(to bottom right, var(--appkit-color-error), var(--appkit-color-primary), var(--appkit-color-warning));
|
|
348
352
|
--appkit-gradient-spotlight: linear-gradient(to bottom right, var(--appkit-color-info-surface), var(--appkit-color-bg), var(--appkit-color-info-surface));
|
|
349
|
-
--appkit-gradient-whatsapp-card: linear-gradient(
|
|
353
|
+
--appkit-gradient-whatsapp-card: linear-gradient(135deg, var(--appkit-color-whatsapp) 0%, var(--appkit-color-whatsapp-light) 48%, var(--appkit-color-whatsapp-dark) 100%);
|
|
350
354
|
--appkit-gradient-glass: linear-gradient(to bottom right, color-mix(in srgb, var(--appkit-color-surface) 85%, transparent), color-mix(in srgb, var(--appkit-color-surface) 65%, transparent));
|
|
351
355
|
--appkit-gradient-card-indigo: linear-gradient(to bottom right, var(--appkit-color-primary-50), var(--appkit-color-surface), var(--appkit-color-surface));
|
|
352
356
|
--appkit-gradient-card-teal: linear-gradient(to bottom right, var(--appkit-color-secondary-50), var(--appkit-color-surface), var(--appkit-color-surface));
|
|
@@ -459,7 +463,7 @@
|
|
|
459
463
|
--appkit-gradient-accent-banner: linear-gradient(to right, var(--appkit-color-primary), var(--appkit-color-secondary));
|
|
460
464
|
--appkit-gradient-promotion: linear-gradient(to bottom right, var(--appkit-color-error), var(--appkit-color-primary), var(--appkit-color-warning));
|
|
461
465
|
--appkit-gradient-spotlight: linear-gradient(to bottom right, rgba(6,182,212,0.10), var(--appkit-color-bg), rgba(6,182,212,0.10));
|
|
462
|
-
--appkit-gradient-whatsapp-card: linear-gradient(
|
|
466
|
+
--appkit-gradient-whatsapp-card: linear-gradient(135deg, var(--appkit-color-whatsapp) 0%, var(--appkit-color-whatsapp-light) 48%, var(--appkit-color-whatsapp-dark) 100%);
|
|
463
467
|
--appkit-gradient-glass: linear-gradient(to bottom right, color-mix(in srgb, var(--appkit-color-surface) 85%, transparent), color-mix(in srgb, var(--appkit-color-surface) 65%, transparent));
|
|
464
468
|
--appkit-gradient-card-indigo: linear-gradient(to bottom right, rgba(239,68,68,0.10), var(--appkit-color-surface), var(--appkit-color-surface));
|
|
465
469
|
--appkit-gradient-card-teal: linear-gradient(to bottom right, rgba(6,182,212,0.10), var(--appkit-color-surface), var(--appkit-color-surface));
|
|
@@ -16,6 +16,17 @@ declare const UI_BUTTON: {
|
|
|
16
16
|
readonly ghost: "appkit-button--ghost";
|
|
17
17
|
readonly danger: "appkit-button--danger";
|
|
18
18
|
readonly warning: "appkit-button--warning";
|
|
19
|
+
/**
|
|
20
|
+
* A surface-coloured pill for use ON a dark or branded background.
|
|
21
|
+
*
|
|
22
|
+
* WHY: all six variants above are tuned for a light page surface and none
|
|
23
|
+
* is legible on a branded one, which is why call sites were overriding the
|
|
24
|
+
* variant with `!important` instead — `WhatsAppCommunitySection` carried
|
|
25
|
+
* four (`!bg-…whatsapp !text-white !border-0`) because a green button on a
|
|
26
|
+
* green card is invisible. Inverting the pairing (surface fill, themed ink)
|
|
27
|
+
* is legible on any backdrop and needs no overrides.
|
|
28
|
+
*/
|
|
29
|
+
readonly inverse: "appkit-button--inverse";
|
|
19
30
|
};
|
|
20
31
|
readonly sizes: {
|
|
21
32
|
readonly sm: "appkit-button--sm";
|
|
@@ -41,6 +41,17 @@ const UI_BUTTON = {
|
|
|
41
41
|
ghost: "appkit-button--ghost",
|
|
42
42
|
danger: "appkit-button--danger",
|
|
43
43
|
warning: "appkit-button--warning",
|
|
44
|
+
/**
|
|
45
|
+
* A surface-coloured pill for use ON a dark or branded background.
|
|
46
|
+
*
|
|
47
|
+
* WHY: all six variants above are tuned for a light page surface and none
|
|
48
|
+
* is legible on a branded one, which is why call sites were overriding the
|
|
49
|
+
* variant with `!important` instead — `WhatsAppCommunitySection` carried
|
|
50
|
+
* four (`!bg-…whatsapp !text-white !border-0`) because a green button on a
|
|
51
|
+
* green card is invisible. Inverting the pairing (surface fill, themed ink)
|
|
52
|
+
* is legible on any backdrop and needs no overrides.
|
|
53
|
+
*/
|
|
54
|
+
inverse: "appkit-button--inverse",
|
|
44
55
|
},
|
|
45
56
|
sizes: {
|
|
46
57
|
sm: "appkit-button--sm",
|
|
@@ -198,6 +198,35 @@
|
|
|
198
198
|
color: inherit;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
/*
|
|
202
|
+
* `inverse` — a surface-coloured pill for a dark or branded backdrop.
|
|
203
|
+
*
|
|
204
|
+
* The pairing is deliberately the inverse of `primary`: the FILL comes from
|
|
205
|
+
* the page surface and the INK from body text, so it contrasts against
|
|
206
|
+
* whatever colour the card behind it is, in both themes, with no per-call-site
|
|
207
|
+
* override. Four `!important` declarations in WhatsAppCommunitySection and one
|
|
208
|
+
* `!bg-primary` on a TextLink in WelcomeSection existed only because this
|
|
209
|
+
* variant did not.
|
|
210
|
+
*
|
|
211
|
+
* No border: a 1px border between a white pill and a saturated card reads as
|
|
212
|
+
* a seam rather than an edge.
|
|
213
|
+
*/
|
|
214
|
+
.appkit-button.appkit-button--inverse {
|
|
215
|
+
background: var(--appkit-color-surface);
|
|
216
|
+
border-color: transparent;
|
|
217
|
+
color: var(--appkit-color-text);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.appkit-button.appkit-button--inverse:hover:not(:disabled) {
|
|
221
|
+
background: color-mix(in srgb, var(--appkit-color-surface) 92%, var(--appkit-color-text));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* Same child-inheritance rule the warning variant needs: a nested element with
|
|
225
|
+
no appkit class of its own must not fall back to the themed body colour. */
|
|
226
|
+
.appkit-button.appkit-button--inverse :not([class*="appkit-"]) {
|
|
227
|
+
color: inherit;
|
|
228
|
+
}
|
|
229
|
+
|
|
201
230
|
.appkit-button__spinner {
|
|
202
231
|
width: 1rem;
|
|
203
232
|
height: 1rem;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* CarouselNav — the one carousel position/navigation control.
|
|
4
|
+
*
|
|
5
|
+
* Presentational ONLY: it owns no scroll state and no timers. A hero passes its
|
|
6
|
+
* slide index; a rail passes `Math.round(scrollLeft / clientWidth)`. See
|
|
7
|
+
* CarouselNav.style.css for why three separate implementations was the defect
|
|
8
|
+
* this replaces.
|
|
9
|
+
*
|
|
10
|
+
* ## 🛑 Not `<Progress>`
|
|
11
|
+
*
|
|
12
|
+
* `Progress` is `role="progressbar"` with `aria-valuenow` — a claim that
|
|
13
|
+
* something is LOADING. An autoplay timer is decorative chrome; announcing it
|
|
14
|
+
* as progress tells a screen-reader user the page is busy when it is not. The
|
|
15
|
+
* fill here is `aria-hidden` and the segments carry the real semantics.
|
|
16
|
+
*
|
|
17
|
+
* @tag domain:ui
|
|
18
|
+
* @tag layer:component
|
|
19
|
+
* @tag pattern:presentational
|
|
20
|
+
* @tag access:client
|
|
21
|
+
* @tag sideEffects:none
|
|
22
|
+
*/
|
|
23
|
+
/** Over imagery, or on a themed page surface. See the CSS for the tone maps. */
|
|
24
|
+
export type CarouselNavTone = "on-media" | "on-surface";
|
|
25
|
+
/**
|
|
26
|
+
* Above this many positions the segment rail becomes unhittable slivers and
|
|
27
|
+
* overflows a phone, so the component switches to a meter plus a counter.
|
|
28
|
+
*/
|
|
29
|
+
export declare const CAROUSEL_RAIL_MAX = 8;
|
|
30
|
+
export interface CarouselNavProps {
|
|
31
|
+
/** Total positions. Below 2 the component renders nothing. */
|
|
32
|
+
count: number;
|
|
33
|
+
/** Current zero-based position. */
|
|
34
|
+
index: number;
|
|
35
|
+
/** Jump to a position. Omit to render the rail as a non-interactive readout. */
|
|
36
|
+
onSelect?: (index: number) => void;
|
|
37
|
+
onPrev?: () => void;
|
|
38
|
+
onNext?: () => void;
|
|
39
|
+
tone?: CarouselNavTone;
|
|
40
|
+
/**
|
|
41
|
+
* Autoplay delay in ms, used ONLY to time the fill inside the active segment.
|
|
42
|
+
* Omit or pass 0 when there is no autoplay — the active segment then renders
|
|
43
|
+
* solid instead of animating. This must be the SAME value that drives the
|
|
44
|
+
* caller's timer; a literal here is the 4s-vs-6000ms desync this replaces.
|
|
45
|
+
*/
|
|
46
|
+
progressMs?: number;
|
|
47
|
+
/** Freezes the fill. Pass the same flag that suspends the caller's timer. */
|
|
48
|
+
paused?: boolean;
|
|
49
|
+
/** Disables `prev` at the first position / `next` at the last. Ignored when `loop`. */
|
|
50
|
+
atStart?: boolean;
|
|
51
|
+
atEnd?: boolean;
|
|
52
|
+
loop?: boolean;
|
|
53
|
+
/** Names the control group. Required — "carousel" alone is not a name. */
|
|
54
|
+
ariaLabel: string;
|
|
55
|
+
className?: string;
|
|
56
|
+
}
|
|
57
|
+
export declare function CarouselNav({ count, index, onSelect, onPrev, onNext, tone, progressMs, paused, atStart, atEnd, loop, ariaLabel, className, }: CarouselNavProps): React.JSX.Element | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
4
|
+
import { ICON_SIZE } from "../icons/icon-registry.js";
|
|
5
|
+
/**
|
|
6
|
+
* Above this many positions the segment rail becomes unhittable slivers and
|
|
7
|
+
* overflows a phone, so the component switches to a meter plus a counter.
|
|
8
|
+
*/
|
|
9
|
+
export const CAROUSEL_RAIL_MAX = 8;
|
|
10
|
+
export function CarouselNav({ count, index, onSelect, onPrev, onNext, tone = "on-surface", progressMs = 0, paused = false, atStart = false, atEnd = false, loop = false, ariaLabel, className = "", }) {
|
|
11
|
+
if (count < 2)
|
|
12
|
+
return null;
|
|
13
|
+
const current = Math.min(Math.max(index, 0), count - 1);
|
|
14
|
+
const hasAutoplay = progressMs > 0;
|
|
15
|
+
const useRail = count <= CAROUSEL_RAIL_MAX;
|
|
16
|
+
const prevDisabled = !loop && atStart;
|
|
17
|
+
const nextDisabled = !loop && atEnd;
|
|
18
|
+
return (_jsxs("div", { className: `appkit-carousel-nav ${className}`, "data-tone": tone, "data-paused": paused ? "true" : "false", "data-autoplay": hasAutoplay ? "true" : "false", style: { "--appkit-carousel-progress-duration": `${progressMs}ms` }, role: "group", "aria-label": ariaLabel, children: [onPrev && (_jsx("button", { type: "button", className: "appkit-carousel-nav__arrow", onClick: onPrev, disabled: prevDisabled, "aria-label": "Previous", children: _jsx(ChevronLeft, { className: ICON_SIZE.lg, "aria-hidden": "true" }) })), useRail ? (_jsx("div", { className: "appkit-carousel-nav__rail", children: Array.from({ length: count }, (_, i) => {
|
|
19
|
+
const isCurrent = i === current;
|
|
20
|
+
return (_jsx("button", { type: "button", className: "appkit-carousel-nav__seg", "aria-current": isCurrent ? "true" : undefined, "aria-label": `Go to ${i + 1} of ${count}`, onClick: onSelect ? () => onSelect(i) : undefined, disabled: !onSelect, children: _jsx("span", { className: "appkit-carousel-nav__bar", children: isCurrent && hasAutoplay && (_jsx("span", { className: "appkit-carousel-nav__fill", "aria-hidden": "true" }, `fill-${current}`)) }) }, i));
|
|
21
|
+
}) })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "appkit-carousel-nav__meter", "aria-hidden": "true", children: _jsx("span", { className: "appkit-carousel-nav__meter-thumb", style: {
|
|
22
|
+
left: `${(current / count) * 100}%`,
|
|
23
|
+
width: `${(1 / count) * 100}%`,
|
|
24
|
+
} }) }), _jsxs("span", { className: "appkit-carousel-nav__count", children: [current + 1, " / ", count] })] })), onNext && (_jsx("button", { type: "button", className: "appkit-carousel-nav__arrow", onClick: onNext, disabled: nextDisabled, "aria-label": "Next", children: _jsx(ChevronRight, { className: ICON_SIZE.lg, "aria-hidden": "true" }) }))] }));
|
|
25
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* CarouselNav — the ONE carousel position/navigation control.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 What it replaces, and why three implementations was the bug
|
|
5
|
+
*
|
|
6
|
+
* There were three unrelated indicator systems on the homepage alone:
|
|
7
|
+
*
|
|
8
|
+
* 1. `features/homepage/constants/hero-carousel-styles.ts` — bespoke Tailwind
|
|
9
|
+
* pill dots plus a separate progress bar, and BOTH arrows stacked in one
|
|
10
|
+
* bottom corner beside the dots.
|
|
11
|
+
* 2. `HorizontalScroller.style.css` — 36px translucent circles at mid-height,
|
|
12
|
+
* `display:none` below 640px, with a 6px scrollbar as the only position
|
|
13
|
+
* cue. Used by SectionCarousel, ShopByCategorySection, BrandsSection and
|
|
14
|
+
* CustomCardsSection, i.e. nearly every rail on the site.
|
|
15
|
+
* 3. `TestimonialsCarousel` — `overflow-x-auto scrollbar-none`, nothing at
|
|
16
|
+
* all, so there was no indication that content continued off-screen.
|
|
17
|
+
*
|
|
18
|
+
* The thing that had to be shared is the APPEARANCE; the call sites differ only
|
|
19
|
+
* in their STATE SOURCE (a hero knows its slide index, a rail derives one from
|
|
20
|
+
* `scrollLeft / clientWidth`). That split is what a presentational primitive is
|
|
21
|
+
* for, and it is why this is a new component rather than two restyles.
|
|
22
|
+
*
|
|
23
|
+
* ## 🛑 Segments, not dots — the active segment IS the progress track
|
|
24
|
+
*
|
|
25
|
+
* The hero previously rendered a progress bar as a child of the active dot and
|
|
26
|
+
* drove it with `animate-[progress-fill_4s_linear_forwards]` — a hardcoded 4s
|
|
27
|
+
* against a seeded `autoplayDelayMs` of 6000, so the bar finished two seconds
|
|
28
|
+
* before the slide moved. A literal cannot track a runtime value. Here the fill
|
|
29
|
+
* is the active segment itself and its duration comes from
|
|
30
|
+
* `--appkit-carousel-progress-duration`, set by the component from the real
|
|
31
|
+
* delay, so the two cannot disagree.
|
|
32
|
+
*
|
|
33
|
+
* ## 🛑 Arrows sit IN the row, not over the track
|
|
34
|
+
*
|
|
35
|
+
* Absolutely-positioning a 44px circle over a single-column card is what forced
|
|
36
|
+
* `display:none` below 640px in the first place, and it also cost every rail
|
|
37
|
+
* 2 × 44px of wrapper gutter to reserve space for controls a phone never saw.
|
|
38
|
+
* In flow, there is no breakpoint at which an affordance disappears and no
|
|
39
|
+
* gutter to reserve — and the arrows stop overlaying product art at a contrast
|
|
40
|
+
* nobody can predict.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
.appkit-carousel-nav {
|
|
44
|
+
--appkit-carousel-seg-w: 1.5rem;
|
|
45
|
+
--appkit-carousel-seg-w-active: 2.5rem;
|
|
46
|
+
--appkit-carousel-seg-h: 0.1875rem; /* 3px */
|
|
47
|
+
--appkit-carousel-arrow-size: 2.75rem; /* 44px — WCAG 2.5.8 target size */
|
|
48
|
+
/* Overridden inline by the component from the REAL autoplay delay. 0ms means
|
|
49
|
+
"no autoplay", which the [data-autoplay="false"] rule below renders as a
|
|
50
|
+
solid active segment rather than an animation of zero length. */
|
|
51
|
+
--appkit-carousel-progress-duration: 0ms;
|
|
52
|
+
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
justify-content: center;
|
|
56
|
+
gap: var(--appkit-space-3, 0.75rem);
|
|
57
|
+
min-height: var(--appkit-carousel-arrow-size);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* --- Tone: the ONLY colour decision in this file ------------------------- */
|
|
61
|
+
|
|
62
|
+
/* Over imagery — white ink on a blurred dark scrim, theme-invariant because a
|
|
63
|
+
product photo is neither light nor dark in a way CSS can know. */
|
|
64
|
+
.appkit-carousel-nav[data-tone="on-media"] {
|
|
65
|
+
--appkit-carousel-track: color-mix(in srgb, #fff 32%, transparent);
|
|
66
|
+
--appkit-carousel-fill: #fff;
|
|
67
|
+
--appkit-carousel-arrow-bg: color-mix(in srgb, #000 38%, transparent);
|
|
68
|
+
--appkit-carousel-arrow-ink: #fff;
|
|
69
|
+
--appkit-carousel-arrow-edge: color-mix(in srgb, #fff 45%, transparent);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* On a themed page surface — follows the active theme in both directions. */
|
|
73
|
+
.appkit-carousel-nav[data-tone="on-surface"] {
|
|
74
|
+
--appkit-carousel-track: var(--appkit-color-border, #e4e4e7);
|
|
75
|
+
--appkit-carousel-fill: var(--appkit-color-primary, #0d9488);
|
|
76
|
+
--appkit-carousel-arrow-bg: var(--appkit-color-surface, #ffffff);
|
|
77
|
+
--appkit-carousel-arrow-ink: var(--appkit-color-text, #18181b);
|
|
78
|
+
--appkit-carousel-arrow-edge: var(--appkit-color-border, #e4e4e7);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* --- Segment rail -------------------------------------------------------- */
|
|
82
|
+
|
|
83
|
+
.appkit-carousel-nav__rail {
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
/* `safe center` rather than `center`: a centred overflowing flex row pushes
|
|
87
|
+
its LEADING items past the start edge, where they are unreachable by any
|
|
88
|
+
scroll gesture. See scripts/audit-centred-scroller.mjs. */
|
|
89
|
+
justify-content: safe center;
|
|
90
|
+
gap: var(--appkit-space-1-5, 0.375rem);
|
|
91
|
+
min-width: 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/*
|
|
95
|
+
* A 3px bar inside a 44px transparent hit box — the TARGET is the button, the
|
|
96
|
+
* VISUAL is the bar. The dots this replaces were `w-2 h-2` with `!min-h-0`,
|
|
97
|
+
* i.e. they actively defeated Button's own minimum target height to reach an
|
|
98
|
+
* 8px tap target.
|
|
99
|
+
*/
|
|
100
|
+
.appkit-carousel-nav__seg {
|
|
101
|
+
display: flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
padding-block: calc((var(--appkit-carousel-arrow-size) - var(--appkit-carousel-seg-h)) / 2);
|
|
104
|
+
padding-inline: 0;
|
|
105
|
+
background: none;
|
|
106
|
+
border: 0;
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
-webkit-tap-highlight-color: transparent;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.appkit-carousel-nav__bar {
|
|
112
|
+
position: relative;
|
|
113
|
+
display: block;
|
|
114
|
+
overflow: hidden;
|
|
115
|
+
width: var(--appkit-carousel-seg-w);
|
|
116
|
+
height: var(--appkit-carousel-seg-h);
|
|
117
|
+
border-radius: 9999px;
|
|
118
|
+
background: var(--appkit-carousel-track);
|
|
119
|
+
transition:
|
|
120
|
+
width 420ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
121
|
+
background 180ms linear;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.appkit-carousel-nav__seg:hover .appkit-carousel-nav__bar,
|
|
125
|
+
.appkit-carousel-nav__seg:focus-visible .appkit-carousel-nav__bar {
|
|
126
|
+
background: color-mix(in srgb, var(--appkit-carousel-fill) 55%, transparent);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.appkit-carousel-nav__seg[aria-current="true"] .appkit-carousel-nav__bar {
|
|
130
|
+
width: var(--appkit-carousel-seg-w-active);
|
|
131
|
+
background: color-mix(in srgb, var(--appkit-carousel-fill) 28%, transparent);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/*
|
|
135
|
+
* `scaleX`, not `width`: it is compositor-only, and it leaves the bar's own
|
|
136
|
+
* `width` transition free to animate the 1.5rem → 2.5rem expansion at the same
|
|
137
|
+
* time without the two fighting over one property.
|
|
138
|
+
*/
|
|
139
|
+
.appkit-carousel-nav__fill {
|
|
140
|
+
position: absolute;
|
|
141
|
+
inset: 0;
|
|
142
|
+
transform-origin: left center;
|
|
143
|
+
background: var(--appkit-carousel-fill);
|
|
144
|
+
animation: appkit-carousel-fill var(--appkit-carousel-progress-duration, 0ms) linear forwards;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Hover-pause previously stopped the setInterval and left the bar filling, so
|
|
148
|
+
the indicator claimed the slide was about to advance while it was held. */
|
|
149
|
+
.appkit-carousel-nav[data-paused="true"] .appkit-carousel-nav__fill {
|
|
150
|
+
animation-play-state: paused;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.appkit-carousel-nav[data-autoplay="false"] .appkit-carousel-nav__fill {
|
|
154
|
+
animation: none;
|
|
155
|
+
transform: scaleX(1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@keyframes appkit-carousel-fill {
|
|
159
|
+
from {
|
|
160
|
+
transform: scaleX(0);
|
|
161
|
+
}
|
|
162
|
+
to {
|
|
163
|
+
transform: scaleX(1);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* --- Arrows -------------------------------------------------------------- */
|
|
168
|
+
|
|
169
|
+
.appkit-carousel-nav__arrow {
|
|
170
|
+
display: inline-flex;
|
|
171
|
+
flex: none;
|
|
172
|
+
align-items: center;
|
|
173
|
+
justify-content: center;
|
|
174
|
+
width: var(--appkit-carousel-arrow-size);
|
|
175
|
+
height: var(--appkit-carousel-arrow-size);
|
|
176
|
+
border-radius: 9999px;
|
|
177
|
+
border: 0;
|
|
178
|
+
background: var(--appkit-carousel-arrow-bg);
|
|
179
|
+
color: var(--appkit-carousel-arrow-ink);
|
|
180
|
+
box-shadow:
|
|
181
|
+
inset 0 0 0 1px var(--appkit-carousel-arrow-edge),
|
|
182
|
+
0 1px 2px color-mix(in srgb, #000 8%, transparent);
|
|
183
|
+
backdrop-filter: blur(10px) saturate(140%);
|
|
184
|
+
cursor: pointer;
|
|
185
|
+
transition:
|
|
186
|
+
transform 180ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
187
|
+
background 180ms linear;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.appkit-carousel-nav__arrow:hover:not(:disabled) {
|
|
191
|
+
transform: scale(1.06);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.appkit-carousel-nav__arrow:active:not(:disabled) {
|
|
195
|
+
transform: scale(0.94);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.appkit-carousel-nav__arrow:disabled,
|
|
199
|
+
.appkit-carousel-nav__arrow[aria-disabled="true"] {
|
|
200
|
+
opacity: 0.4;
|
|
201
|
+
pointer-events: none;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* --- Counter mode ------------------------------------------------------- */
|
|
205
|
+
|
|
206
|
+
/*
|
|
207
|
+
* Above CAROUSEL_RAIL_MAX positions the segments become unhittable slivers and
|
|
208
|
+
* the row overflows a phone, so a long rail shows one continuous meter plus a
|
|
209
|
+
* tabular "4 / 17" instead. Dropping to a counter is a real affordance; a row
|
|
210
|
+
* of forty 2px dots is not.
|
|
211
|
+
*/
|
|
212
|
+
.appkit-carousel-nav__meter {
|
|
213
|
+
position: relative;
|
|
214
|
+
overflow: hidden;
|
|
215
|
+
width: clamp(4rem, 18vw, 9rem);
|
|
216
|
+
height: var(--appkit-carousel-seg-h);
|
|
217
|
+
border-radius: 9999px;
|
|
218
|
+
background: var(--appkit-carousel-track);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.appkit-carousel-nav__meter-thumb {
|
|
222
|
+
position: absolute;
|
|
223
|
+
inset-block: 0;
|
|
224
|
+
border-radius: 9999px;
|
|
225
|
+
background: var(--appkit-carousel-fill);
|
|
226
|
+
transition: left 320ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.appkit-carousel-nav__count {
|
|
230
|
+
font-variant-numeric: tabular-nums;
|
|
231
|
+
font-size: var(--appkit-text-xs, 0.75rem);
|
|
232
|
+
color: var(--appkit-carousel-arrow-ink);
|
|
233
|
+
white-space: nowrap;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* --- Compact (phones) --------------------------------------------------- */
|
|
237
|
+
|
|
238
|
+
@media (max-width: 639px) {
|
|
239
|
+
.appkit-carousel-nav {
|
|
240
|
+
--appkit-carousel-seg-w: 1rem;
|
|
241
|
+
--appkit-carousel-seg-w-active: 1.75rem;
|
|
242
|
+
gap: var(--appkit-space-2, 0.5rem);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* --- Inside a HorizontalScroller ---------------------------------------- */
|
|
247
|
+
|
|
248
|
+
/* Breathing room between the rail and its indicator. A margin here rather than
|
|
249
|
+
a gap on `.appkit-hscroller`, because that wrapper is also the positioning
|
|
250
|
+
context for the absolute arrows and a gap would move them. */
|
|
251
|
+
.appkit-hscroller__nav {
|
|
252
|
+
margin-top: var(--appkit-space-3, 0.75rem);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
@media (prefers-reduced-motion: reduce) {
|
|
256
|
+
.appkit-carousel-nav__fill {
|
|
257
|
+
animation: none;
|
|
258
|
+
transform: scaleX(1);
|
|
259
|
+
}
|
|
260
|
+
.appkit-carousel-nav__bar,
|
|
261
|
+
.appkit-carousel-nav__meter-thumb,
|
|
262
|
+
.appkit-carousel-nav__arrow {
|
|
263
|
+
transition: none;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
3
4
|
import { Span } from "./Typography.js";
|
|
4
5
|
import { Row } from "./Layout.js";
|
|
5
|
-
import {
|
|
6
|
+
import { Icon } from "./Icon.js";
|
|
7
|
+
import { IconButton, ICON_BUTTON_ICON_SIZE } from "./IconButton.js";
|
|
8
|
+
import { LoginRequiredModal } from "./LoginRequiredModal.js";
|
|
6
9
|
import { getDefaultCurrency } from "../../core/baseline-resolver.js";
|
|
7
10
|
import { formatCurrency, formatPercentage } from "../../utils/number.formatter.js";
|
|
8
11
|
import { useCanSeePrices } from "../../react/hooks/useCanSeePrices.js";
|
|
@@ -24,6 +27,30 @@ import { useCanSeePrices } from "../../react/hooks/useCanSeePrices.js";
|
|
|
24
27
|
// audit-dead-css-ok: selector target for the paywall JSON-LD, never styled
|
|
25
28
|
export const GATED_PRICE_CLASS = "appkit-gated-price";
|
|
26
29
|
const DEFAULT_LABEL = "Sign in to see price";
|
|
30
|
+
/**
|
|
31
|
+
* The signed-out state: a closed eye you can press, not a line of refusal copy.
|
|
32
|
+
*
|
|
33
|
+
* 🛑 WHY AN ICON AND NOT THE SENTENCE. The prompt used to be a full
|
|
34
|
+
* "🔒 Sign in to see price" link in `--appkit-color-primary`, repeated once per
|
|
35
|
+
* card. On a 24-card grid that is 24 lines of brand-coloured refusal, each
|
|
36
|
+
* wider than the price it stands in for — so the grid's loudest element became
|
|
37
|
+
* the thing the visitor cannot have, and the rows it sat in changed width with
|
|
38
|
+
* the copy. An eye occupies roughly a price's worth of space, reads as "there
|
|
39
|
+
* is something here", and says it once per card without shouting.
|
|
40
|
+
*
|
|
41
|
+
* 🛑 THE ASK IS ON THE CLICK, NOT ON THE PAGE. Pressing it opens the shared
|
|
42
|
+
* sign-in modal rather than navigating away: a visitor who taps a price on a
|
|
43
|
+
* listing page wants the price, not to lose their place in the catalogue. The
|
|
44
|
+
* modal is rendered only while open, so a grid of 24 gated prices mounts 24
|
|
45
|
+
* buttons and zero modals.
|
|
46
|
+
*
|
|
47
|
+
* The accessible name is still the full sentence — the icon is the visual
|
|
48
|
+
* economy, not an information loss.
|
|
49
|
+
*/
|
|
50
|
+
function GatedPriceReveal({ label }) {
|
|
51
|
+
const [asking, setAsking] = React.useState(false);
|
|
52
|
+
return (_jsxs(_Fragment, { children: [_jsx(IconButton, { size: "sm", variant: "outline", rounded: "lg", "aria-label": label, title: label, onClick: () => setAsking(true), icon: _jsx(Icon, { name: "hide", size: ICON_BUTTON_ICON_SIZE.sm }) }), asking && (_jsx(LoginRequiredModal, { isOpen: true, onClose: () => setAsking(false), message: `${label}. Sign in or create an account to see prices across the site.` }))] }));
|
|
53
|
+
}
|
|
27
54
|
/**
|
|
28
55
|
* Renders its children only when the viewer may see prices; renders NOTHING
|
|
29
56
|
* otherwise — no prompt, no placeholder.
|
|
@@ -65,7 +92,7 @@ export function GatedPrice({ amount, currency = getDefaultCurrency(), originalAm
|
|
|
65
92
|
return (_jsx(Span, { className: `${rootClass} appkit-gated-price__pending`, "aria-hidden": "true" }));
|
|
66
93
|
}
|
|
67
94
|
if (!canSeePrices) {
|
|
68
|
-
return (_jsx(
|
|
95
|
+
return (_jsx(Span, { className: `${rootClass} appkit-gated-price__prompt`, children: _jsx(GatedPriceReveal, { label: label }) }));
|
|
69
96
|
}
|
|
70
97
|
if (children !== undefined) {
|
|
71
98
|
return _jsx(Span, { className: rootClass, children: children });
|
|
@@ -1,40 +1,43 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sign-in gate for money amounts on public listing surfaces.
|
|
3
|
-
*
|
|
4
|
-
* The pending state must occupy the SAME vertical space as a rendered price, or
|
|
5
|
-
* every card in a grid reflows once the session resolves. It is deliberately a
|
|
6
|
-
* silent placeholder rather than a shimmer: the wait is short, and an animated
|
|
7
|
-
* skeleton on 24 cards reads as a page that failed to load.
|
|
8
|
-
*/
|
|
9
|
-
.appkit-gated-price__pending {
|
|
10
|
-
display: inline-block;
|
|
11
|
-
min-width: 5rem;
|
|
12
|
-
height: 1.25rem;
|
|
13
|
-
border-radius: 0.25rem;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Sign-in gate for money amounts on public listing surfaces.
|
|
3
|
+
*
|
|
4
|
+
* The pending state must occupy the SAME vertical space as a rendered price, or
|
|
5
|
+
* every card in a grid reflows once the session resolves. It is deliberately a
|
|
6
|
+
* silent placeholder rather than a shimmer: the wait is short, and an animated
|
|
7
|
+
* skeleton on 24 cards reads as a page that failed to load.
|
|
8
|
+
*/
|
|
9
|
+
.appkit-gated-price__pending {
|
|
10
|
+
display: inline-block;
|
|
11
|
+
min-width: 5rem;
|
|
12
|
+
height: 1.25rem;
|
|
13
|
+
border-radius: 0.25rem;
|
|
14
|
+
/* 🛑 `--appkit-color-surface-muted` is NOT a token — 15 uses, 0 definitions,
|
|
15
|
+
and `audit-undefined-css-vars` ratchets it down. An undefined custom
|
|
16
|
+
property with no fallback makes the whole declaration invalid, so this
|
|
17
|
+
placeholder had no background at all and the grid still reflowed on
|
|
18
|
+
resolve, which is the one job it has. */
|
|
19
|
+
background: var(--appkit-color-surface-input);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.appkit-gated-price__prompt {
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
/*
|
|
26
|
+
* The eye is a 2rem IconButton while `__pending` above is a 1.25rem price
|
|
27
|
+
* line, so a GUEST's row grows by 0.75rem once the session resolves. That is
|
|
28
|
+
* deliberate and is the lesser of the two: the alternative is making
|
|
29
|
+
* `__pending` 2rem, which shifts the row for SIGNED-IN users — the ones who
|
|
30
|
+
* end up looking at real content. The guest shift happens once per load and
|
|
31
|
+
* applies to every card identically, so the grid moves as one rather than
|
|
32
|
+
* going ragged.
|
|
33
|
+
*/
|
|
34
|
+
line-height: 1.25rem;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* 🛑 The eye itself has NO rules here, on purpose. It is an `<IconButton
|
|
39
|
+
* size="sm" variant="outline">`, so its box, ink, hover and focus ring all
|
|
40
|
+
* come from the design system — a second, private set of button styles for
|
|
41
|
+
* one control is exactly how a UI ends up with two kinds of icon button that
|
|
42
|
+
* drift apart. This wrapper only has to keep the row's height stable.
|
|
43
|
+
*/
|
|
@@ -36,5 +36,16 @@ export interface HorizontalScrollerProps<T = unknown> {
|
|
|
36
36
|
itemClassName?: string;
|
|
37
37
|
/** When the scroller reaches the last item, snap instantly back to the first instead of stopping. */
|
|
38
38
|
loop?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Render a `CarouselNav` position indicator below the rail.
|
|
41
|
+
*
|
|
42
|
+
* Opt-in rather than default: this is a visible layout change and the rail is
|
|
43
|
+
* used on roughly every listing surface in the app. Pair it with
|
|
44
|
+
* `showArrows={false}` — the in-flow nav carries its own arrows, so leaving
|
|
45
|
+
* both on gives a surface two sets of controls that do the same thing.
|
|
46
|
+
*/
|
|
47
|
+
showNav?: boolean;
|
|
48
|
+
/** Names the nav group. Defaults to a generic label; pass the rail's subject. */
|
|
49
|
+
navAriaLabel?: string;
|
|
39
50
|
}
|
|
40
|
-
export declare function HorizontalScroller<T = unknown>({ children, className, gap, snapToItems, showArrows, arrowSize, arrowStyle, showScrollbar, scrollContainerRef: externalRef, onScroll, items, renderItem, keyExtractor, perView, rows, autoScroll, autoScrollInterval, minItemWidth, pauseOnHover, itemClassName, loop, }: HorizontalScrollerProps<T>): import("react").JSX.Element;
|
|
51
|
+
export declare function HorizontalScroller<T = unknown>({ children, className, gap, snapToItems, showArrows, arrowSize, arrowStyle, showScrollbar, scrollContainerRef: externalRef, onScroll, items, renderItem, keyExtractor, perView, rows, autoScroll, autoScrollInterval, minItemWidth, pauseOnHover, itemClassName, loop, showNav, navAriaLabel, }: HorizontalScrollerProps<T>): import("react").JSX.Element;
|