@mohasinac/appkit 2.3.2 → 2.4.1
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/client.d.ts +48 -12
- package/dist/client.js +25 -6
- package/dist/constants/api-endpoints.d.ts +380 -22
- package/dist/constants/api-endpoints.js +66 -13
- package/dist/constants/index.d.ts +1 -1
- package/dist/constants/index.js +1 -1
- package/dist/core/hooks/useSyncManager.d.ts +1 -0
- package/dist/core/hooks/useSyncManager.js +83 -0
- package/dist/core/integration-keys.d.ts +4 -0
- package/dist/core/integration-keys.js +8 -0
- package/dist/features/about/components/FAQPageView.js +9 -11
- package/dist/features/about/components/PolicyPageView.js +32 -11
- package/dist/features/about/components/PublicProfileView.js +77 -11
- package/dist/features/account/components/AddressesIndexListing.js +63 -38
- package/dist/features/account/components/UserOffersPanel.d.ts +8 -0
- package/dist/features/account/components/UserOffersPanel.js +81 -0
- package/dist/features/account/components/UserSettingsView.d.ts +2 -1
- package/dist/features/account/components/UserSettingsView.js +2 -1
- package/dist/features/account/components/UserSidebar.d.ts +6 -1
- package/dist/features/account/components/UserSidebar.js +48 -42
- package/dist/features/account/components/index.d.ts +2 -0
- package/dist/features/account/components/index.js +1 -0
- package/dist/features/admin/actions/admin-actions.d.ts +1 -1
- package/dist/features/admin/actions/admin-actions.js +13 -3
- package/dist/features/admin/components/AdminAdEditorView.js +6 -7
- package/dist/features/admin/components/AdminAllEventEntriesView.d.ts +4 -0
- package/dist/features/admin/components/AdminAllEventEntriesView.js +102 -0
- package/dist/features/admin/components/AdminBidsView.js +94 -8
- package/dist/features/admin/components/AdminBlogEditorView.d.ts +7 -0
- package/dist/features/admin/components/AdminBlogEditorView.js +162 -0
- package/dist/features/admin/components/AdminBlogView.d.ts +4 -1
- package/dist/features/admin/components/AdminBlogView.js +61 -31
- package/dist/features/admin/components/AdminBrandEditorView.d.ts +7 -0
- package/dist/features/admin/components/AdminBrandEditorView.js +104 -0
- package/dist/features/admin/components/AdminBrandsView.d.ts +4 -0
- package/dist/features/admin/components/AdminBrandsView.js +76 -0
- package/dist/features/admin/components/AdminCarouselEditorView.d.ts +8 -0
- package/dist/features/admin/components/AdminCarouselEditorView.js +204 -0
- package/dist/features/admin/components/AdminCarouselView.js +153 -34
- package/dist/features/admin/components/AdminCartsView.d.ts +4 -0
- package/dist/features/admin/components/AdminCartsView.js +82 -0
- package/dist/features/admin/components/AdminCategoriesView.d.ts +4 -1
- package/dist/features/admin/components/AdminCategoriesView.js +66 -48
- package/dist/features/admin/components/AdminCategoryEditorView.d.ts +7 -0
- package/dist/features/admin/components/AdminCategoryEditorView.js +115 -0
- package/dist/features/admin/components/AdminContactEditorView.d.ts +11 -0
- package/dist/features/admin/components/AdminContactEditorView.js +32 -0
- package/dist/features/admin/components/AdminContactView.js +111 -20
- package/dist/features/admin/components/AdminCouponEditorView.d.ts +7 -0
- package/dist/features/admin/components/AdminCouponEditorView.js +179 -0
- package/dist/features/admin/components/AdminCouponsView.d.ts +4 -1
- package/dist/features/admin/components/AdminCouponsView.js +57 -9
- package/dist/features/admin/components/AdminDashboardView.js +3 -0
- package/dist/features/admin/components/AdminFaqEditorView.d.ts +7 -0
- package/dist/features/admin/components/AdminFaqEditorView.js +128 -0
- package/dist/features/admin/components/AdminFaqsView.d.ts +4 -1
- package/dist/features/admin/components/AdminFaqsView.js +55 -23
- package/dist/features/admin/components/AdminFeatureFlagsView.js +33 -24
- package/dist/features/admin/components/AdminListingScaffold.d.ts +7 -1
- package/dist/features/admin/components/AdminListingScaffold.js +2 -2
- package/dist/features/admin/components/AdminMediaView.js +18 -8
- package/dist/features/admin/components/AdminNavEditorView.d.ts +20 -0
- package/dist/features/admin/components/AdminNavEditorView.js +84 -0
- package/dist/features/admin/components/AdminNavigationView.d.ts +1 -7
- package/dist/features/admin/components/AdminNavigationView.js +84 -72
- package/dist/features/admin/components/AdminNewsletterView.js +102 -20
- package/dist/features/admin/components/AdminNotificationsView.d.ts +4 -0
- package/dist/features/admin/components/AdminNotificationsView.js +119 -0
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +8 -0
- package/dist/features/admin/components/AdminOrderEditorView.js +74 -0
- package/dist/features/admin/components/AdminOrdersView.js +64 -8
- package/dist/features/admin/components/AdminPayoutsView.js +122 -13
- package/dist/features/admin/components/AdminProductEditorView.d.ts +7 -0
- package/dist/features/admin/components/AdminProductEditorView.js +143 -0
- package/dist/features/admin/components/AdminProductsView.d.ts +4 -1
- package/dist/features/admin/components/AdminProductsView.js +119 -30
- package/dist/features/admin/components/AdminReturnRequestsView.d.ts +5 -0
- package/dist/features/admin/components/AdminReturnRequestsView.js +101 -0
- package/dist/features/admin/components/AdminReviewsView.js +138 -28
- package/dist/features/admin/components/AdminSectionsView.js +361 -472
- package/dist/features/admin/components/AdminSessionsView.d.ts +4 -0
- package/dist/features/admin/components/AdminSessionsView.js +119 -0
- package/dist/features/admin/components/AdminSidebar.d.ts +18 -3
- package/dist/features/admin/components/AdminSidebar.js +51 -4
- package/dist/features/admin/components/AdminSiteSettingsView.d.ts +7 -0
- package/dist/features/admin/components/AdminSiteSettingsView.js +319 -0
- package/dist/features/admin/components/AdminStoreAddressesView.d.ts +5 -0
- package/dist/features/admin/components/AdminStoreAddressesView.js +52 -0
- package/dist/features/admin/components/AdminStoreEditorView.d.ts +9 -0
- package/dist/features/admin/components/AdminStoreEditorView.js +55 -0
- package/dist/features/admin/components/AdminStoresView.js +62 -20
- package/dist/features/admin/components/AdminUserEditorView.d.ts +10 -0
- package/dist/features/admin/components/AdminUserEditorView.js +72 -0
- package/dist/features/admin/components/AdminUsersView.js +70 -36
- package/dist/features/admin/components/AdminWishlistsView.d.ts +4 -0
- package/dist/features/admin/components/AdminWishlistsView.js +53 -0
- package/dist/features/admin/components/BrandQuickCreateForm.d.ts +5 -0
- package/dist/features/admin/components/BrandQuickCreateForm.js +36 -0
- package/dist/features/admin/components/CategoryQuickCreateForm.d.ts +5 -0
- package/dist/features/admin/components/CategoryQuickCreateForm.js +35 -0
- package/dist/features/admin/components/DataTable.d.ts +4 -2
- package/dist/features/admin/components/DataTable.js +26 -6
- package/dist/features/admin/components/index.d.ts +47 -1
- package/dist/features/admin/components/index.js +23 -0
- package/dist/features/admin/components/sections/adminSectionsBuildParse.d.ts +48 -0
- package/dist/features/admin/components/sections/adminSectionsBuildParse.js +653 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.d.ts +298 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.js +278 -0
- package/dist/features/admin/schemas/firestore.d.ts +26 -0
- package/dist/features/admin/schemas/firestore.js +1 -0
- package/dist/features/admin/types/product.types.d.ts +2 -3
- package/dist/features/auctions/actions/bid-actions.js +6 -2
- package/dist/features/auctions/components/AuctionDetailPageView.d.ts +3 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +38 -12
- package/dist/features/auctions/components/AuctionFilters.d.ts +3 -1
- package/dist/features/auctions/components/AuctionFilters.js +6 -2
- package/dist/features/auctions/components/CollapsibleBidHistory.d.ts +7 -0
- package/dist/features/auctions/components/CollapsibleBidHistory.js +8 -0
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +4 -0
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +43 -9
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +1 -0
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +18 -0
- package/dist/features/auctions/components/PlaceBidFormClient.js +33 -0
- package/dist/features/auctions/hooks/useAuctions.d.ts +1 -0
- package/dist/features/auctions/hooks/useAuctions.js +1 -0
- package/dist/features/auctions/schemas/index.d.ts +22 -12
- package/dist/features/auth/actions/profile-actions.d.ts +5 -3
- package/dist/features/auth/actions/profile-actions.js +30 -11
- package/dist/features/auth/auth-helpers.js +1 -0
- package/dist/features/auth/components/LoginForm.js +2 -1
- package/dist/features/auth/hooks/useAuth.js +16 -4
- package/dist/features/auth/permissions/constants.d.ts +63 -0
- package/dist/features/auth/permissions/constants.js +323 -0
- package/dist/features/auth/schemas/firestore.d.ts +20 -0
- package/dist/features/auth/schemas/index.d.ts +4 -4
- package/dist/features/auth/schemas/index.js +3 -2
- package/dist/features/auth/types/index.d.ts +1 -1
- package/dist/features/before-after/schemas/index.d.ts +2 -2
- package/dist/features/blog/actions/blog-actions.d.ts +15 -15
- package/dist/features/blog/components/BlogFilters.js +1 -1
- package/dist/features/blog/components/BlogIndexListing.js +57 -5
- package/dist/features/blog/components/BlogIndexPageView.js +14 -2
- package/dist/features/blog/components/BlogPostForm.js +6 -2
- package/dist/features/blog/components/BlogPostView.js +2 -1
- package/dist/features/blog/hooks/useBlog.d.ts +2 -0
- package/dist/features/blog/hooks/useBlog.js +2 -0
- package/dist/features/blog/schemas/index.d.ts +46 -12
- package/dist/features/brands/actions/brand-actions.d.ts +2 -0
- package/dist/features/brands/actions/brand-actions.js +5 -0
- package/dist/features/brands/index.d.ts +3 -0
- package/dist/features/brands/index.js +3 -0
- package/dist/features/brands/repository/brands.repository.d.ts +13 -0
- package/dist/features/brands/repository/brands.repository.js +60 -0
- package/dist/features/brands/schemas/index.d.ts +33 -0
- package/dist/features/brands/schemas/index.js +15 -0
- package/dist/features/brands/server.d.ts +7 -0
- package/dist/features/brands/server.js +7 -0
- package/dist/features/cart/actions/cart-actions.js +2 -2
- package/dist/features/cart/components/CartDrawer.d.ts +5 -1
- package/dist/features/cart/components/CartDrawer.js +3 -3
- package/dist/features/cart/hooks/useCartCount.d.ts +3 -2
- package/dist/features/cart/hooks/useCartCount.js +4 -2
- package/dist/features/cart/hooks/useGuestCartMerge.js +1 -1
- package/dist/features/cart/index.d.ts +1 -0
- package/dist/features/cart/index.js +1 -0
- package/dist/features/cart/repository/cart.repository.d.ts +5 -1
- package/dist/features/cart/repository/cart.repository.js +36 -5
- package/dist/features/cart/schemas/firestore.d.ts +25 -6
- package/dist/features/cart/schemas/firestore.js +2 -2
- package/dist/features/cart/schemas/index.d.ts +9 -9
- package/dist/features/cart/schemas/index.js +1 -1
- package/dist/features/cart/types/index.d.ts +1 -1
- package/dist/features/cart/utils/pending-ops.d.ts +33 -0
- package/dist/features/cart/utils/pending-ops.js +102 -0
- package/dist/features/categories/components/BrandDetailPageView.d.ts +4 -0
- package/dist/features/categories/components/BrandDetailPageView.js +54 -0
- package/dist/features/categories/components/BrandDetailTabs.d.ts +10 -0
- package/dist/features/categories/components/BrandDetailTabs.js +22 -0
- package/dist/features/categories/components/CategoriesIndexListing.d.ts +3 -1
- package/dist/features/categories/components/CategoriesIndexListing.js +83 -7
- package/dist/features/categories/components/CategoryDetailPageView.js +42 -21
- package/dist/features/categories/components/CategoryDetailTabs.d.ts +7 -1
- package/dist/features/categories/components/CategoryDetailTabs.js +12 -7
- package/dist/features/categories/components/CategoryFilters.js +1 -1
- package/dist/features/categories/components/CategoryForm.js +10 -4
- package/dist/features/categories/components/CategoryProductsListing.d.ts +4 -1
- package/dist/features/categories/components/CategoryProductsListing.js +34 -5
- package/dist/features/categories/components/ConcernCard.js +1 -1
- package/dist/features/categories/hooks/useCategories.js +2 -0
- package/dist/features/categories/repository/categories.repository.js +2 -3
- package/dist/features/categories/schemas/firestore.d.ts +23 -2
- package/dist/features/categories/schemas/firestore.js +8 -0
- package/dist/features/categories/schemas/index.d.ts +8 -8
- package/dist/features/categories/types/index.d.ts +1 -0
- package/dist/features/collections/schemas/index.d.ts +2 -2
- package/dist/features/events/components/AdminEventEditorView.js +2 -2
- package/dist/features/events/components/AdminEventsView.d.ts +4 -1
- package/dist/features/events/components/AdminEventsView.js +64 -38
- package/dist/features/events/components/EventCard.js +1 -1
- package/dist/features/events/components/EventFilters.js +1 -1
- package/dist/features/events/components/EventPollWidget.d.ts +12 -0
- package/dist/features/events/components/EventPollWidget.js +62 -0
- package/dist/features/events/components/EventsIndexListing.js +57 -5
- package/dist/features/events/components/EventsListPageView.js +1 -1
- package/dist/features/events/components/index.d.ts +2 -0
- package/dist/features/events/components/index.js +1 -0
- package/dist/features/events/hooks/useEvents.d.ts +1 -0
- package/dist/features/events/hooks/useEvents.js +1 -0
- package/dist/features/events/repository/events.repository.js +3 -0
- package/dist/features/events/schemas/firestore.d.ts +1 -0
- package/dist/features/events/schemas/index.d.ts +44 -0
- package/dist/features/events/types/index.d.ts +2 -0
- package/dist/features/faq/actions/faq-actions.d.ts +16 -16
- package/dist/features/faq/hooks/useFaqList.js +1 -1
- package/dist/features/faq/schemas/firestore.d.ts +2 -2
- package/dist/features/faq/schemas/firestore.js +2 -1
- package/dist/features/faq/schemas/index.d.ts +4 -4
- package/dist/features/filters/FilterFacetSection.d.ts +1 -0
- package/dist/features/filters/FilterFacetSection.js +13 -1
- package/dist/features/filters/SwitchFilter.js +1 -1
- package/dist/features/grouped/schemas/firestore.d.ts +32 -0
- package/dist/features/grouped/schemas/firestore.js +19 -0
- package/dist/features/homepage/components/AdSlot.d.ts +1 -3
- package/dist/features/homepage/components/AdSlot.js +15 -14
- package/dist/features/homepage/components/BlogArticlesSection.d.ts +3 -1
- package/dist/features/homepage/components/BlogArticlesSection.js +2 -2
- package/dist/features/homepage/components/BrandsSection.d.ts +3 -1
- package/dist/features/homepage/components/BrandsSection.js +4 -3
- package/dist/features/homepage/components/CustomCardsSection.d.ts +3 -0
- package/dist/features/homepage/components/CustomCardsSection.js +76 -0
- package/dist/features/homepage/components/EventsSection.d.ts +3 -1
- package/dist/features/homepage/components/EventsSection.js +2 -2
- package/dist/features/homepage/components/FeaturedAuctionsSection.d.ts +4 -1
- package/dist/features/homepage/components/FeaturedAuctionsSection.js +2 -2
- package/dist/features/homepage/components/FeaturedPreOrdersSection.d.ts +4 -1
- package/dist/features/homepage/components/FeaturedPreOrdersSection.js +2 -2
- package/dist/features/homepage/components/FeaturedProductsSection.d.ts +4 -1
- package/dist/features/homepage/components/FeaturedProductsSection.js +8 -3
- package/dist/features/homepage/components/FeaturedStoresSection.d.ts +3 -1
- package/dist/features/homepage/components/FeaturedStoresSection.js +2 -2
- package/dist/features/homepage/components/GoogleReviewsSection.d.ts +3 -0
- package/dist/features/homepage/components/GoogleReviewsSection.js +65 -0
- package/dist/features/homepage/components/HeroCarousel.js +128 -84
- package/dist/features/homepage/components/MarketplaceHomepageView.d.ts +2 -20
- package/dist/features/homepage/components/MarketplaceHomepageView.js +73 -230
- package/dist/features/homepage/components/SectionCarousel.d.ts +1 -1
- package/dist/features/homepage/components/SectionCarousel.js +2 -0
- package/dist/features/homepage/components/ShopByCategorySection.d.ts +3 -1
- package/dist/features/homepage/components/ShopByCategorySection.js +8 -4
- package/dist/features/homepage/components/SocialFeedSection.d.ts +3 -0
- package/dist/features/homepage/components/SocialFeedSection.js +86 -0
- package/dist/features/homepage/components/SocialPostCard.d.ts +7 -0
- package/dist/features/homepage/components/SocialPostCard.js +39 -0
- package/dist/features/homepage/components/StatsCounterSection.js +1 -1
- package/dist/features/homepage/components/WelcomeSection.js +1 -1
- package/dist/features/homepage/components/WhatsAppCommunitySection.js +1 -1
- package/dist/features/homepage/hooks/useActiveAd.d.ts +23 -0
- package/dist/features/homepage/hooks/useActiveAd.js +20 -0
- package/dist/features/homepage/hooks/useBlogArticles.d.ts +1 -0
- package/dist/features/homepage/hooks/useBlogArticles.js +10 -0
- package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +4 -1
- package/dist/features/homepage/hooks/useFeaturedAuctions.js +8 -4
- package/dist/features/homepage/hooks/useFeaturedPreOrders.d.ts +4 -1
- package/dist/features/homepage/hooks/useFeaturedPreOrders.js +8 -4
- package/dist/features/homepage/hooks/useFeaturedProducts.d.ts +1 -0
- package/dist/features/homepage/hooks/useFeaturedProducts.js +6 -3
- package/dist/features/homepage/hooks/useFeaturedStores.d.ts +3 -1
- package/dist/features/homepage/hooks/useFeaturedStores.js +2 -1
- package/dist/features/homepage/hooks/useHomepageEvents.d.ts +3 -1
- package/dist/features/homepage/hooks/useHomepageEvents.js +2 -1
- package/dist/features/homepage/hooks/useTopBrands.d.ts +3 -1
- package/dist/features/homepage/hooks/useTopBrands.js +2 -1
- package/dist/features/homepage/index.d.ts +2 -0
- package/dist/features/homepage/index.js +1 -0
- package/dist/features/homepage/lib/google-reviews-fetcher.d.ts +14 -0
- package/dist/features/homepage/lib/google-reviews-fetcher.js +27 -0
- package/dist/features/homepage/lib/live-stats.d.ts +14 -0
- package/dist/features/homepage/lib/live-stats.js +62 -0
- package/dist/features/homepage/lib/section-defaults.d.ts +11 -0
- package/dist/features/homepage/lib/section-defaults.js +45 -0
- package/dist/features/homepage/lib/section-helpers.d.ts +5 -0
- package/dist/features/homepage/lib/section-helpers.js +25 -0
- package/dist/features/homepage/lib/section-renderer.d.ts +33 -0
- package/dist/features/homepage/lib/section-renderer.js +164 -0
- package/dist/features/homepage/lib/social-feed-fetcher.d.ts +5 -0
- package/dist/features/homepage/lib/social-feed-fetcher.js +193 -0
- package/dist/features/homepage/schemas/firestore.d.ts +180 -29
- package/dist/features/homepage/schemas/firestore.js +5 -0
- package/dist/features/homepage/types/index.d.ts +48 -19
- package/dist/features/layout/AppLayoutShell.d.ts +6 -1
- package/dist/features/layout/AppLayoutShell.js +25 -9
- package/dist/features/layout/BottomActions.js +1 -1
- package/dist/features/layout/BottomNavbar.d.ts +15 -1
- package/dist/features/layout/BottomNavbar.js +8 -2
- package/dist/features/layout/FooterLayout.d.ts +7 -1
- package/dist/features/layout/FooterLayout.js +3 -3
- package/dist/features/layout/ListingLayout.js +2 -2
- package/dist/features/layout/MainNavbar.d.ts +6 -14
- package/dist/features/layout/MainNavbar.js +4 -16
- package/dist/features/layout/NavItem.js +1 -1
- package/dist/features/layout/NavbarLayout.d.ts +3 -1
- package/dist/features/layout/NavbarLayout.js +5 -5
- package/dist/features/layout/TitleBar.d.ts +4 -2
- package/dist/features/layout/TitleBar.js +5 -3
- package/dist/features/layout/TitleBarLayout.d.ts +3 -1
- package/dist/features/layout/TitleBarLayout.js +2 -2
- package/dist/features/layout/index.d.ts +1 -1
- package/dist/features/media/MediaPickerModal.d.ts +30 -0
- package/dist/features/media/MediaPickerModal.js +72 -0
- package/dist/features/media/index.d.ts +3 -1
- package/dist/features/media/index.js +1 -0
- package/dist/features/media/types/index.d.ts +12 -0
- package/dist/features/media/types/index.js +4 -2
- package/dist/features/media/upload/MediaUploadField.d.ts +5 -1
- package/dist/features/media/upload/MediaUploadField.js +56 -3
- package/dist/features/messages/schemas/firestore.d.ts +36 -0
- package/dist/features/messages/schemas/firestore.js +16 -0
- package/dist/features/orders/repository/orders.repository.d.ts +2 -2
- package/dist/features/orders/repository/orders.repository.js +2 -2
- package/dist/features/orders/schemas/firestore.d.ts +17 -4
- package/dist/features/orders/schemas/firestore.js +2 -2
- package/dist/features/orders/schemas/index.d.ts +18 -18
- package/dist/features/orders/schemas/index.js +3 -3
- package/dist/features/orders/types/index.d.ts +1 -1
- package/dist/features/orders/utils/order-splitter.d.ts +1 -1
- package/dist/features/orders/utils/order-splitter.js +2 -2
- package/dist/features/payments/repository/payout.repository.d.ts +4 -4
- package/dist/features/payments/repository/payout.repository.js +7 -7
- package/dist/features/payments/schemas/firestore.d.ts +6 -6
- package/dist/features/payments/schemas/firestore.js +6 -6
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +11 -10
- package/dist/features/pre-orders/components/PreOrderActionsClient.d.ts +11 -0
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +28 -0
- package/dist/features/pre-orders/components/PreOrderDetailPageView.d.ts +2 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +27 -9
- package/dist/features/pre-orders/components/PreOrderFilters.d.ts +3 -1
- package/dist/features/pre-orders/components/PreOrderFilters.js +9 -6
- package/dist/features/pre-orders/components/PreOrdersIndexListing.d.ts +3 -1
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +132 -36
- package/dist/features/pre-orders/components/PreOrdersListView.js +3 -3
- package/dist/features/pre-orders/components/PreorderCard.js +1 -1
- package/dist/features/pre-orders/schemas/index.d.ts +10 -0
- package/dist/features/products/actions/product-actions.d.ts +2 -2
- package/dist/features/products/actions/product-actions.js +5 -5
- package/dist/features/products/api/[id]/route.js +5 -2
- package/dist/features/products/api/route.js +10 -14
- package/dist/features/products/columns/productTableColumns.js +2 -2
- package/dist/features/products/components/AuctionDetailView.d.ts +2 -1
- package/dist/features/products/components/AuctionDetailView.js +2 -2
- package/dist/features/products/components/AuctionsIndexListing.d.ts +3 -1
- package/dist/features/products/components/AuctionsIndexListing.js +93 -31
- package/dist/features/products/components/BidHistory.d.ts +2 -1
- package/dist/features/products/components/BidHistory.js +18 -2
- package/dist/features/products/components/MakeOfferButton.d.ts +10 -0
- package/dist/features/products/components/MakeOfferButton.js +68 -0
- package/dist/features/products/components/ProductDetailPageView.d.ts +11 -1
- package/dist/features/products/components/ProductDetailPageView.js +27 -8
- package/dist/features/products/components/ProductFilters.d.ts +7 -1
- package/dist/features/products/components/ProductFilters.js +4 -2
- package/dist/features/products/components/ProductForm.d.ts +19 -1
- package/dist/features/products/components/ProductForm.js +24 -6
- package/dist/features/products/components/ProductGrid.d.ts +10 -2
- package/dist/features/products/components/ProductGrid.js +76 -29
- package/dist/features/products/components/ProductsIndexListing.js +131 -45
- package/dist/features/products/components/RelatedProductsCarousel.js +1 -1
- package/dist/features/products/components/ShareButton.d.ts +7 -0
- package/dist/features/products/components/ShareButton.js +22 -0
- package/dist/features/products/components/index.d.ts +2 -0
- package/dist/features/products/components/index.js +1 -0
- package/dist/features/products/hooks/useProducts.d.ts +7 -0
- package/dist/features/products/hooks/useProducts.js +6 -4
- package/dist/features/products/repository/products.repository.d.ts +4 -8
- package/dist/features/products/repository/products.repository.js +17 -50
- package/dist/features/products/schemas/firestore.d.ts +11 -9
- package/dist/features/products/schemas/firestore.js +11 -3
- package/dist/features/products/schemas/index.d.ts +51 -50
- package/dist/features/products/schemas/index.js +2 -5
- package/dist/features/products/types/index.d.ts +13 -5
- package/dist/features/promotions/actions/coupon-actions.d.ts +2 -2
- package/dist/features/promotions/actions/coupon-actions.js +1 -1
- package/dist/features/promotions/actions/seller-coupon-actions.js +11 -6
- package/dist/features/promotions/api/route.js +3 -3
- package/dist/features/promotions/components/CouponCard.js +16 -7
- package/dist/features/promotions/components/CouponsIndexListing.js +3 -9
- package/dist/features/promotions/hooks/useCouponValidate.d.ts +1 -1
- package/dist/features/promotions/hooks/usePromotions.js +2 -2
- package/dist/features/promotions/repository/coupons.repository.d.ts +21 -15
- package/dist/features/promotions/repository/coupons.repository.js +97 -125
- package/dist/features/promotions/schemas/firestore.d.ts +31 -2
- package/dist/features/promotions/schemas/firestore.js +29 -0
- package/dist/features/promotions/schemas/index.d.ts +9 -12
- package/dist/features/promotions/schemas/index.js +1 -2
- package/dist/features/promotions/types/index.d.ts +1 -2
- package/dist/features/reviews/actions/review-actions.js +3 -2
- package/dist/features/reviews/components/ReviewDetailPageView.js +5 -9
- package/dist/features/reviews/components/ReviewFilters.js +1 -1
- package/dist/features/reviews/components/ReviewsIndexListing.js +58 -7
- package/dist/features/reviews/components/ReviewsList.js +2 -2
- package/dist/features/reviews/hooks/useReviews.d.ts +1 -0
- package/dist/features/reviews/hooks/useReviews.js +2 -1
- package/dist/features/reviews/repository/reviews.repository.d.ts +9 -4
- package/dist/features/reviews/repository/reviews.repository.js +18 -7
- package/dist/features/reviews/schemas/firestore.d.ts +5 -2
- package/dist/features/reviews/schemas/firestore.js +1 -0
- package/dist/features/reviews/schemas/index.d.ts +19 -16
- package/dist/features/reviews/schemas/index.js +3 -2
- package/dist/features/reviews/types/index.d.ts +3 -2
- package/dist/features/scams/actions/scam-actions.d.ts +29 -0
- package/dist/features/scams/actions/scam-actions.js +62 -0
- package/dist/features/scams/components/ScamProfileView.d.ts +10 -0
- package/dist/features/scams/components/ScamProfileView.js +51 -0
- package/dist/features/scams/components/ScamRegistryView.d.ts +6 -0
- package/dist/features/scams/components/ScamRegistryView.js +41 -0
- package/dist/features/scams/components/index.d.ts +4 -0
- package/dist/features/scams/components/index.js +2 -0
- package/dist/features/scams/constants/scam-types.d.ts +38 -0
- package/dist/features/scams/constants/scam-types.js +443 -0
- package/dist/features/scams/repository/scammer.repository.d.ts +67 -0
- package/dist/features/scams/repository/scammer.repository.js +160 -0
- package/dist/features/scams/schemas/firestore.d.ts +362 -0
- package/dist/features/scams/schemas/firestore.js +233 -0
- package/dist/features/search/components/Search.d.ts +12 -2
- package/dist/features/search/components/Search.js +26 -7
- package/dist/features/search/components/index.d.ts +1 -1
- package/dist/features/search/hooks/useNavSuggestions.d.ts +1 -1
- package/dist/features/search/hooks/useNavSuggestions.js +2 -2
- package/dist/features/search/schemas/index.d.ts +7 -7
- package/dist/features/seller/actions/offer-actions.js +52 -36
- package/dist/features/seller/actions/seller-actions.js +19 -13
- package/dist/features/seller/api/products/route.js +9 -4
- package/dist/features/seller/components/SellerAddressesView.d.ts +3 -12
- package/dist/features/seller/components/SellerAddressesView.js +144 -4
- package/dist/features/seller/components/SellerAuctionsView.js +58 -5
- package/dist/features/seller/components/SellerBidsView.d.ts +4 -0
- package/dist/features/seller/components/SellerBidsView.js +131 -0
- package/dist/features/seller/components/SellerCouponEditorView.d.ts +19 -0
- package/dist/features/seller/components/SellerCouponEditorView.js +67 -0
- package/dist/features/seller/components/SellerCouponsView.d.ts +5 -3
- package/dist/features/seller/components/SellerCouponsView.js +135 -13
- package/dist/features/seller/components/SellerCreateProductView.d.ts +4 -10
- package/dist/features/seller/components/SellerCreateProductView.js +4 -3
- package/dist/features/seller/components/SellerEditProductView.d.ts +4 -10
- package/dist/features/seller/components/SellerEditProductView.js +4 -3
- package/dist/features/seller/components/SellerOffersPanel.d.ts +20 -0
- package/dist/features/seller/components/SellerOffersPanel.js +138 -0
- package/dist/features/seller/components/SellerOffersView.js +56 -5
- package/dist/features/seller/components/SellerOrdersView.d.ts +2 -1
- package/dist/features/seller/components/SellerOrdersView.js +185 -16
- package/dist/features/seller/components/SellerPayoutRequestView.d.ts +7 -0
- package/dist/features/seller/components/SellerPayoutRequestView.js +63 -0
- package/dist/features/seller/components/SellerPayoutSettingsView.d.ts +3 -10
- package/dist/features/seller/components/SellerPayoutSettingsView.js +89 -3
- package/dist/features/seller/components/SellerPayoutsView.js +56 -5
- package/dist/features/seller/components/SellerProductShell.d.ts +68 -0
- package/dist/features/seller/components/SellerProductShell.js +179 -0
- package/dist/features/seller/components/SellerProductsView.d.ts +2 -3
- package/dist/features/seller/components/SellerProductsView.js +194 -18
- package/dist/features/seller/components/SellerReviewsView.d.ts +5 -0
- package/dist/features/seller/components/SellerReviewsView.js +100 -0
- package/dist/features/seller/components/SellerShippingView.d.ts +3 -11
- package/dist/features/seller/components/SellerShippingView.js +87 -3
- package/dist/features/seller/components/SellerSidebar.d.ts +11 -3
- package/dist/features/seller/components/SellerSidebar.js +52 -8
- package/dist/features/seller/components/SellerStorefrontView.d.ts +26 -11
- package/dist/features/seller/components/SellerStorefrontView.js +45 -7
- package/dist/features/seller/components/index.d.ts +16 -2
- package/dist/features/seller/components/index.js +7 -0
- package/dist/features/seller/hooks/useSellerListingData.d.ts +3 -1
- package/dist/features/seller/hooks/useSellerListingData.js +6 -4
- package/dist/features/seller/repository/offer.repository.d.ts +3 -3
- package/dist/features/seller/repository/offer.repository.js +6 -6
- package/dist/features/seller/schemas/firestore.d.ts +7 -7
- package/dist/features/seller/schemas/firestore.js +4 -4
- package/dist/features/seller/schemas/index.d.ts +16 -16
- package/dist/features/shell/FormShell.d.ts +29 -0
- package/dist/features/shell/FormShell.js +103 -0
- package/dist/features/shell/QuickFormDrawer.d.ts +29 -0
- package/dist/features/shell/QuickFormDrawer.js +117 -0
- package/dist/features/shell/StepForm.d.ts +44 -0
- package/dist/features/shell/StepForm.js +81 -0
- package/dist/features/shell/index.d.ts +6 -0
- package/dist/features/shell/index.js +3 -0
- package/dist/features/stores/actions/store-query-actions.js +3 -3
- package/dist/features/stores/api/[storeSlug]/auctions/route.js +1 -1
- package/dist/features/stores/api/[storeSlug]/products/route.js +1 -1
- package/dist/features/stores/api/[storeSlug]/reviews/route.js +1 -1
- package/dist/features/stores/components/InteractiveStoreCard.d.ts +2 -2
- package/dist/features/stores/components/InteractiveStoreCard.js +21 -7
- package/dist/features/stores/components/StoreAboutView.js +1 -1
- package/dist/features/stores/components/StoreAuctionsListing.d.ts +5 -2
- package/dist/features/stores/components/StoreAuctionsListing.js +81 -8
- package/dist/features/stores/components/StoreAuctionsPageView.js +8 -7
- package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -0
- package/dist/features/stores/components/StoreDetailLayoutView.js +29 -5
- package/dist/features/stores/components/StoreHeader.js +2 -1
- package/dist/features/stores/components/StorePreOrdersListing.d.ts +4 -2
- package/dist/features/stores/components/StorePreOrdersListing.js +59 -7
- package/dist/features/stores/components/StorePreOrdersPageView.js +8 -7
- package/dist/features/stores/components/StoreProductsListing.d.ts +5 -2
- package/dist/features/stores/components/StoreProductsListing.js +97 -8
- package/dist/features/stores/components/StoreProductsPageView.js +8 -7
- package/dist/features/stores/components/StoreReviewsListing.js +2 -2
- package/dist/features/stores/components/StoresIndexListing.js +74 -11
- package/dist/features/stores/components/StoresListView.js +1 -1
- package/dist/features/stores/hooks/useStores.d.ts +1 -0
- package/dist/features/stores/hooks/useStores.js +1 -0
- package/dist/features/stores/schemas/firestore.d.ts +34 -0
- package/dist/features/stores/schemas/index.d.ts +8 -8
- package/dist/features/sublisting/schemas/firestore.d.ts +30 -0
- package/dist/features/sublisting/schemas/firestore.js +19 -0
- package/dist/features/support/schemas/firestore.d.ts +113 -0
- package/dist/features/support/schemas/firestore.js +95 -0
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.d.ts +5 -0
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +143 -0
- package/dist/features/whatsapp-bot/components/index.d.ts +2 -0
- package/dist/features/whatsapp-bot/components/index.js +1 -0
- package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +23 -1
- package/dist/features/whatsapp-bot/helpers/whatsapp.js +104 -0
- package/dist/features/whatsapp-bot/server.d.ts +1 -0
- package/dist/features/whatsapp-bot/server.js +1 -0
- package/dist/features/whatsapp-bot/types/index.d.ts +49 -0
- package/dist/features/wishlist/components/WishlistView.d.ts +0 -10
- package/dist/features/wishlist/components/WishlistView.js +13 -6
- package/dist/features/wishlist/hooks/useWishlist.js +2 -0
- package/dist/features/wishlist/hooks/useWishlistCount.d.ts +11 -3
- package/dist/features/wishlist/hooks/useWishlistCount.js +89 -25
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/features/wishlist/schemas/index.d.ts +2 -2
- package/dist/features/wishlist/types/index.d.ts +16 -0
- package/dist/http/api-handler.js +8 -1
- package/dist/index.d.ts +114 -16
- package/dist/index.js +136 -28
- package/dist/monitoring/server-logger.js +9 -3
- package/dist/next/routing/route-map.d.ts +120 -6
- package/dist/next/routing/route-map.js +53 -2
- package/dist/providers/db-firebase/realtime.d.ts +1 -1
- package/dist/react/contexts/SessionContext.js +17 -26
- package/dist/react/hooks/useBulkSelection.d.ts +7 -24
- package/dist/react/hooks/useBulkSelection.js +27 -34
- package/dist/react/hooks/useLongPress.d.ts +3 -16
- package/dist/react/hooks/useLongPress.js +6 -25
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +2 -0
- package/dist/repositories/index.d.ts +3 -0
- package/dist/repositories/index.js +2 -0
- package/dist/seed/actions/demo-seed-actions.d.ts +2 -2
- package/dist/seed/actions/demo-seed-actions.js +1 -1
- package/dist/seed/anime-figures-seed-data.d.ts +8 -0
- package/dist/seed/anime-figures-seed-data.js +1033 -0
- package/dist/seed/beyblade-seed-data.js +206 -24
- package/dist/seed/bids-seed-data.d.ts +4 -10
- package/dist/seed/bids-seed-data.js +365 -238
- package/dist/seed/blog-posts-seed-data.d.ts +3 -2
- package/dist/seed/blog-posts-seed-data.js +250 -511
- package/dist/seed/brands-seed-data.d.ts +7 -0
- package/dist/seed/brands-seed-data.js +410 -0
- package/dist/seed/carousel-slides-seed-data.d.ts +3 -2
- package/dist/seed/carousel-slides-seed-data.js +177 -216
- package/dist/seed/cart-seed-data.d.ts +9 -9
- package/dist/seed/cart-seed-data.js +73 -73
- package/dist/seed/categories-seed-data.d.ts +4 -2
- package/dist/seed/categories-seed-data.js +720 -879
- package/dist/seed/conversations-seed-data.d.ts +8 -0
- package/dist/seed/conversations-seed-data.js +388 -0
- package/dist/seed/cosplay-accessories-seed-data.d.ts +8 -0
- package/dist/seed/cosplay-accessories-seed-data.js +647 -0
- package/dist/seed/coupon-usage-seed-data.d.ts +25 -0
- package/dist/seed/coupon-usage-seed-data.js +69 -0
- package/dist/seed/coupons-seed-data.d.ts +6 -3
- package/dist/seed/coupons-seed-data.js +375 -3
- package/dist/seed/events-seed-data.d.ts +4 -2
- package/dist/seed/events-seed-data.js +128 -430
- package/dist/seed/factories/cart.factory.d.ts +0 -1
- package/dist/seed/factories/cart.factory.js +2 -2
- package/dist/seed/faq-seed-data.d.ts +11 -18
- package/dist/seed/faq-seed-data.js +786 -1817
- package/dist/seed/grouped-listings-seed-data.d.ts +8 -0
- package/dist/seed/grouped-listings-seed-data.js +201 -0
- package/dist/seed/homepage-sections-seed-data.d.ts +3 -13
- package/dist/seed/homepage-sections-seed-data.js +228 -252
- package/dist/seed/hot-wheels-seed-data.js +285 -38
- package/dist/seed/index.d.ts +12 -11
- package/dist/seed/index.js +10 -12
- package/dist/seed/letitrip-official-seed-data.d.ts +8 -0
- package/dist/seed/letitrip-official-seed-data.js +399 -0
- package/dist/seed/manifest.d.ts +15 -0
- package/dist/seed/manifest.js +140 -0
- package/dist/seed/notifications-seed-data.d.ts +4 -2
- package/dist/seed/notifications-seed-data.js +117 -440
- package/dist/seed/orders-seed-data.d.ts +4 -2
- package/dist/seed/orders-seed-data.js +1090 -521
- package/dist/seed/payouts-seed-data.d.ts +4 -2
- package/dist/seed/payouts-seed-data.js +522 -145
- package/dist/seed/pokemon-carousel-slides-seed-data.js +6 -1
- package/dist/seed/pokemon-categories-seed-data.js +81 -81
- package/dist/seed/pokemon-homepage-sections-seed-data.d.ts +1 -1
- package/dist/seed/pokemon-homepage-sections-seed-data.js +116 -23
- package/dist/seed/pokemon-products-seed-data.d.ts +1 -1
- package/dist/seed/pokemon-products-seed-data.js +83 -73
- package/dist/seed/pokemon-seed-bundle.d.ts +5 -1
- package/dist/seed/pokemon-seed-bundle.js +21 -2
- package/dist/seed/pokemon-stores-seed-data.js +85 -9
- package/dist/seed/pokemon-users-seed-data.js +107 -8
- package/dist/seed/products-auctions-seed-data.d.ts +10 -0
- package/dist/seed/products-auctions-seed-data.js +689 -0
- package/dist/seed/products-preorders-seed-data.d.ts +9 -0
- package/dist/seed/products-preorders-seed-data.js +483 -0
- package/dist/seed/products-seed-data.js +34 -13
- package/dist/seed/products-standard-seed-data.d.ts +8 -0
- package/dist/seed/products-standard-seed-data.js +4179 -0
- package/dist/seed/retro-gaming-seed-data.d.ts +8 -0
- package/dist/seed/retro-gaming-seed-data.js +801 -0
- package/dist/seed/reviews-seed-data.d.ts +4 -17
- package/dist/seed/reviews-seed-data.js +1043 -515
- package/dist/seed/scammers-seed-data.d.ts +17 -0
- package/dist/seed/scammers-seed-data.js +118 -0
- package/dist/seed/site-settings-seed-data.js +25 -2
- package/dist/seed/store-addresses-seed-data.js +188 -84
- package/dist/seed/stores-seed-data.d.ts +3 -9
- package/dist/seed/stores-seed-data.js +212 -102
- package/dist/seed/sublisting-categories-seed-data.d.ts +7 -0
- package/dist/seed/sublisting-categories-seed-data.js +315 -0
- package/dist/seed/transformers-seed-data.js +34 -14
- package/dist/seed/users-seed-data.d.ts +3 -2
- package/dist/seed/users-seed-data.js +531 -440
- package/dist/seed/wishlists-seed-data.js +13 -13
- package/dist/server.d.ts +9 -2
- package/dist/server.js +12 -4
- package/dist/tokens/tokens.css +76 -31
- package/dist/ui/components/Avatar.style.css +10 -12
- package/dist/ui/components/BaseListingCard.d.ts +8 -3
- package/dist/ui/components/BaseListingCard.js +17 -6
- package/dist/ui/components/BaseListingCard.style.css +3 -1
- package/dist/ui/components/BulkActionsBar.d.ts +16 -0
- package/dist/ui/components/BulkActionsBar.js +22 -0
- package/dist/ui/components/Button.style.css +23 -23
- package/dist/ui/components/Card.style.css +60 -62
- package/dist/ui/components/Checkbox.style.css +19 -21
- package/dist/ui/components/DashboardStatsCard.style.css +12 -14
- package/dist/ui/components/Drawer.style.css +18 -14
- package/dist/ui/components/Dropdown.style.css +25 -27
- package/dist/ui/components/EmptyState.style.css +2 -4
- package/dist/ui/components/HorizontalScroller.d.ts +3 -1
- package/dist/ui/components/HorizontalScroller.js +116 -21
- package/dist/ui/components/HorizontalScroller.style.css +2 -2
- package/dist/ui/components/ImageLightbox.d.ts +0 -9
- package/dist/ui/components/ImageLightbox.js +43 -9
- package/dist/ui/components/InlineCreateSelect.d.ts +38 -0
- package/dist/ui/components/InlineCreateSelect.js +70 -0
- package/dist/ui/components/ListingLayout.style.css +41 -77
- package/dist/ui/components/ListingToolbar.d.ts +54 -0
- package/dist/ui/components/ListingToolbar.js +34 -0
- package/dist/ui/components/Modal.style.css +14 -10
- package/dist/ui/components/PageLoader.d.ts +11 -0
- package/dist/ui/components/PageLoader.js +21 -0
- package/dist/ui/components/Radio.style.css +34 -36
- package/dist/ui/components/RichTextEditor.js +1 -1
- package/dist/ui/components/RowActionMenu.d.ts +1 -0
- package/dist/ui/components/RowActionMenu.js +4 -2
- package/dist/ui/components/SectionTabs.js +1 -1
- package/dist/ui/components/SectionTabs.style.css +1 -0
- package/dist/ui/components/SideModal.style.css +4 -8
- package/dist/ui/components/Slider.style.css +2 -4
- package/dist/ui/components/Tabs.style.css +8 -10
- package/dist/ui/components/Toast.style.css +22 -24
- package/dist/ui/components/Toggle.style.css +11 -13
- package/dist/ui/index.d.ts +9 -0
- package/dist/ui/index.js +5 -0
- package/dist/ui/rich-text/RichText.js +2 -1
- package/dist/ui/rich-text/RichText.style.css +292 -5
- package/dist/ui/rich-text/RichTextRenderer.d.ts +15 -0
- package/dist/ui/rich-text/RichTextRenderer.js +15 -0
- package/dist/utils/id-generators.d.ts +10 -0
- package/dist/utils/id-generators.js +12 -0
- package/dist/validation/schemas.d.ts +9 -9
- package/package.json +5 -1
- package/README.md +0 -116
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface BottomNavItem {
|
|
3
|
+
key: string;
|
|
4
|
+
href: string;
|
|
5
|
+
label: string;
|
|
6
|
+
icon?: React.ReactNode;
|
|
7
|
+
}
|
|
1
8
|
export interface BottomNavbarUser {
|
|
2
9
|
displayName: string | null;
|
|
3
10
|
email: string | null;
|
|
@@ -34,6 +41,13 @@ export interface BottomNavbarProps {
|
|
|
34
41
|
loginHref: string;
|
|
35
42
|
/** Called when the Search slot is tapped */
|
|
36
43
|
onSearchToggle?: () => void;
|
|
44
|
+
/**
|
|
45
|
+
* When provided, renders these items in the bottom nav (first 4 shown, 5th slot = "More" button).
|
|
46
|
+
* Overrides the hardcoded Home/Shop/Search/Cart/Profile layout.
|
|
47
|
+
*/
|
|
48
|
+
navItems?: BottomNavItem[];
|
|
49
|
+
/** Called when the "More" slot is tapped (typically opens the sidebar drawer). */
|
|
50
|
+
onMoreToggle?: () => void;
|
|
37
51
|
/** CSS class applied to the active nav item. Default: "text-primary-600 dark:text-primary-400" */
|
|
38
52
|
activeClassName?: string;
|
|
39
53
|
/** CSS class applied to inactive nav items. Default: "text-zinc-500 dark:text-slate-400" */
|
|
@@ -50,4 +64,4 @@ export interface BottomNavbarProps {
|
|
|
50
64
|
*
|
|
51
65
|
* Pass `user` from your auth context to render the profile slot with avatar.
|
|
52
66
|
*/
|
|
53
|
-
export declare function BottomNavbar({ user, homeHref, shopHref, cartHref, profileHref, loginHref, onSearchToggle, activeClassName, inactiveClassName, iconClassName, labelClassName, getRoleBadgeClass, }: BottomNavbarProps): import("react/jsx-runtime").JSX.Element;
|
|
67
|
+
export declare function BottomNavbar({ user, homeHref, shopHref, cartHref, profileHref, loginHref, onSearchToggle, navItems, onMoreToggle, activeClassName, inactiveClassName, iconClassName, labelClassName, getRoleBadgeClass, }: BottomNavbarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -9,7 +9,7 @@ import { NavItem } from "./NavItem";
|
|
|
9
9
|
*
|
|
10
10
|
* Pass `user` from your auth context to render the profile slot with avatar.
|
|
11
11
|
*/
|
|
12
|
-
export function BottomNavbar({ user, homeHref, shopHref, cartHref, profileHref, loginHref, onSearchToggle, activeClassName = "text-primary-600 dark:text-primary-400", inactiveClassName = "text-zinc-500 dark:text-slate-400", iconClassName, labelClassName = "text-[11px] leading-tight font-medium", getRoleBadgeClass, }) {
|
|
12
|
+
export function BottomNavbar({ user, homeHref, shopHref, cartHref, profileHref, loginHref, onSearchToggle, navItems, onMoreToggle, activeClassName = "text-primary-600 dark:text-primary-400", inactiveClassName = "text-zinc-500 dark:text-slate-400", iconClassName, labelClassName = "text-[11px] leading-tight font-medium", getRoleBadgeClass, }) {
|
|
13
13
|
const pathname = usePathname();
|
|
14
14
|
const labels = {
|
|
15
15
|
mobileNav: "Mobile navigation",
|
|
@@ -18,9 +18,15 @@ export function BottomNavbar({ user, homeHref, shopHref, cartHref, profileHref,
|
|
|
18
18
|
search: "Search",
|
|
19
19
|
cart: "Cart",
|
|
20
20
|
profile: "Profile",
|
|
21
|
+
more: "More",
|
|
21
22
|
};
|
|
22
|
-
const itemStyle = { width: "20%" };
|
|
23
23
|
const slotClassName = "relative flex h-full w-full flex-col items-center justify-center gap-1 transition-colors duration-200";
|
|
24
|
+
const defaultIcon = (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 12h16M4 18h16" }) }));
|
|
25
|
+
if (navItems && navItems.length > 0) {
|
|
26
|
+
const visibleItems = navItems.slice(0, 4);
|
|
27
|
+
return (_jsxs(BottomNavLayout, { ariaLabel: labels.mobileNav, children: [visibleItems.map((item) => (_jsx(Li, { className: "flex-1", children: _jsx(NavItem, { href: item.href, label: item.label, icon: item.icon ?? defaultIcon, isActive: pathname === item.href || (item.href !== "/" && pathname.startsWith(item.href + "/")), variant: "vertical", activeClassName: activeClassName, inactiveClassName: inactiveClassName, iconClassName: iconClassName, labelClassName: labelClassName }) }, item.key))), _jsx(Li, { className: "flex-1", children: _jsxs("button", { type: "button", onClick: onMoreToggle, className: `${slotClassName} ${inactiveClassName}`, "aria-label": labels.more, children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 12h16M4 18h16" }) }), _jsx(Span, { className: labelClassName, children: labels.more })] }) })] }));
|
|
28
|
+
}
|
|
29
|
+
const itemStyle = { width: "20%" };
|
|
24
30
|
return (_jsxs(BottomNavLayout, { ariaLabel: labels.mobileNav, children: [_jsx(Li, { className: "flex-1", style: itemStyle, children: _jsx(NavItem, { href: homeHref, label: labels.home, icon: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" }) }), isActive: pathname === homeHref, variant: "vertical", activeClassName: activeClassName, inactiveClassName: inactiveClassName, iconClassName: iconClassName, labelClassName: labelClassName }) }), _jsx(Li, { className: "flex-1", style: itemStyle, children: _jsx(NavItem, { href: shopHref, label: labels.products, icon: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }), isActive: pathname === shopHref, variant: "vertical", activeClassName: activeClassName, inactiveClassName: inactiveClassName, iconClassName: iconClassName, labelClassName: labelClassName }) }), _jsx(Li, { className: "flex-1", style: itemStyle, children: _jsxs("button", { type: "button", onClick: onSearchToggle, className: `${slotClassName} ${inactiveClassName}`, "aria-label": labels.search, children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }), _jsx(Span, { className: labelClassName, children: labels.search })] }) }), _jsx(Li, { className: "flex-1", style: itemStyle, children: _jsxs(TextLink, { href: cartHref, variant: "none", className: `${slotClassName} ${pathname === cartHref ? activeClassName : inactiveClassName}`, "aria-label": labels.cart, children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" }) }), _jsx(Span, { className: labelClassName, children: labels.cart })] }) }), _jsx(Li, { className: "flex-1", style: itemStyle, children: user ? (_jsxs(TextLink, { href: profileHref, variant: "none", className: `${slotClassName} ${pathname === profileHref ? activeClassName : inactiveClassName}`, "aria-label": labels.profile, children: [_jsx(AvatarDisplay, { cropData: user.avatarMetadata ||
|
|
25
31
|
(user.photoURL ? { url: user.photoURL, position: { x: 50, y: 50 }, zoom: 1 } : null), size: "sm", alt: user.displayName || "User", displayName: user.displayName, email: user.email }), user.role && (_jsx(Span, { className: `text-[7px] font-semibold uppercase leading-none ${getRoleBadgeClass ? getRoleBadgeClass(user.role) : "text-zinc-500 dark:text-slate-400"}`, children: user.role }))] })) : (_jsx(NavItem, { href: loginHref, label: labels.profile, icon: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" }) }), isActive: pathname === loginHref, variant: "vertical", activeClassName: activeClassName, inactiveClassName: inactiveClassName, iconClassName: iconClassName, labelClassName: labelClassName })) })] }));
|
|
26
32
|
}
|
|
@@ -21,6 +21,10 @@ export interface TrustBarItem {
|
|
|
21
21
|
subtitle?: string;
|
|
22
22
|
visible?: boolean;
|
|
23
23
|
}
|
|
24
|
+
export interface FooterBottomLink {
|
|
25
|
+
label: string;
|
|
26
|
+
href: string;
|
|
27
|
+
}
|
|
24
28
|
export interface FooterLayoutProps {
|
|
25
29
|
brandName: string;
|
|
26
30
|
brandDescription: string;
|
|
@@ -34,6 +38,8 @@ export interface FooterLayoutProps {
|
|
|
34
38
|
/** When true, renders the trust bar above the main footer content. */
|
|
35
39
|
showTrustBar?: boolean;
|
|
36
40
|
trustBarItems?: TrustBarItem[];
|
|
41
|
+
/** SEO/utility links shown in the bottom bar (sitemap, robots, etc.) */
|
|
42
|
+
bottomLinks?: FooterBottomLink[];
|
|
37
43
|
id?: string;
|
|
38
44
|
}
|
|
39
|
-
export declare function FooterLayout({ brandName, brandDescription, socialLinks, linkGroups, copyrightText, madeInText, newsletterSlot, newsletterEnabled, showTrustBar, trustBarItems, id, }: FooterLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
45
|
+
export declare function FooterLayout({ brandName, brandDescription, socialLinks, linkGroups, copyrightText, madeInText, newsletterSlot, newsletterEnabled, showTrustBar, trustBarItems, bottomLinks, id, }: FooterLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,12 +3,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import Link from "next/link";
|
|
4
4
|
import { useState } from "react";
|
|
5
5
|
import { ChevronDown } from "lucide-react";
|
|
6
|
-
import { BlockFooter, Div, Heading, Li, Row, Span, Text, Ul, } from "../../ui";
|
|
7
|
-
export function FooterLayout({ brandName, brandDescription, socialLinks, linkGroups, copyrightText, madeInText, newsletterSlot, newsletterEnabled = true, showTrustBar = false, trustBarItems = [], id = "footer", }) {
|
|
6
|
+
import { BlockFooter, Button, Div, Heading, Li, Row, Span, Text, Ul, } from "../../ui";
|
|
7
|
+
export function FooterLayout({ brandName, brandDescription, socialLinks, linkGroups, copyrightText, madeInText, newsletterSlot, newsletterEnabled = true, showTrustBar = false, trustBarItems = [], bottomLinks = [], id = "footer", }) {
|
|
8
8
|
const [openGroups, setOpenGroups] = useState({});
|
|
9
9
|
const toggleGroup = (idx) => setOpenGroups((prev) => ({ ...prev, [idx]: !prev[idx] }));
|
|
10
10
|
const visibleTrustItems = trustBarItems.filter((item) => item.visible !== false);
|
|
11
11
|
return (_jsxs(BlockFooter, { id: id, className: "bg-zinc-50 dark:bg-slate-950 border-t border-zinc-200 dark:border-slate-800", children: [showTrustBar && visibleTrustItems.length > 0 && (_jsx(Div, { className: "border-b border-zinc-100 dark:border-slate-800 py-8", children: _jsx(Div, { className: "container mx-auto px-4 sm:px-6 lg:px-8 max-w-[1920px]", children: _jsx(Row, { as: "ul", wrap: true, justify: "center", gap: "lg", className: "lg:gap-10", children: visibleTrustItems.map((item, i) => (_jsx(Li, { children: _jsxs(Row, { gap: "sm", className: "text-sm min-w-[160px]", children: [_jsx(Span, { className: "flex-shrink-0 text-primary-600 dark:text-secondary-400 w-5 h-5", children: item.icon }), _jsxs(Span, { children: [_jsx(Span, { className: "font-bold text-zinc-900 dark:text-zinc-100 block text-sm", children: item.label }), item.subtitle && (_jsx(Span, { className: "text-zinc-500 dark:text-zinc-400 text-xs block", children: item.subtitle }))] })] }) }, item.id ?? String(i)))) }) }) })), _jsxs(Div, { className: "container mx-auto px-4 sm:px-6 lg:px-8 max-w-[1920px] py-10 lg:py-14", children: [_jsxs(Div, { className: "grid grid-cols-1 lg:grid-cols-5 gap-10 lg:gap-16", children: [_jsxs(Div, { className: "lg:col-span-2 space-y-4", children: [_jsx(Heading, { level: 5, className: "text-zinc-900 dark:text-zinc-50 font-bold text-xl", children: brandName }), _jsx(Text, { className: "text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed max-w-sm", children: brandDescription }), socialLinks.length > 0 && (_jsx(Row, { as: Ul, gap: "sm", children: socialLinks.map((link) => (_jsx(Li, { children: _jsx(Link, { href: link.href, "aria-label": link.ariaLabel, target: "_blank", rel: "noopener noreferrer", className: "flex items-center justify-center w-9 h-9 rounded-full border border-zinc-200 dark:border-slate-700 text-zinc-500 dark:text-zinc-400 hover:text-primary dark:hover:text-secondary hover:border-primary/40 dark:hover:border-secondary/40 transition-colors", children: link.icon }) }, link.platform))) })), newsletterEnabled && newsletterSlot && (_jsx(Div, { className: "pt-2", children: newsletterSlot }))] }), _jsx(Div, { className: `lg:col-span-3 grid grid-cols-1 gap-0 lg:gap-8 ${linkGroups.length <= 3 ? "lg:grid-cols-3" :
|
|
12
12
|
linkGroups.length === 4 ? "lg:grid-cols-4" :
|
|
13
|
-
"lg:grid-cols-5"}`, children: linkGroups.map((group, idx) => (_jsxs(Div, { children: [_jsxs(
|
|
13
|
+
"lg:grid-cols-5"}`, children: linkGroups.map((group, idx) => (_jsxs(Div, { children: [_jsxs(Button, { type: "button", variant: "ghost", onClick: () => toggleGroup(idx), className: "flex w-full items-center justify-between border-b border-zinc-200 py-3 text-left text-sm font-semibold text-zinc-800 transition-colors hover:text-zinc-950 dark:border-slate-800 dark:text-zinc-100 dark:hover:text-white lg:hidden", "aria-expanded": !!openGroups[idx], children: [group.heading, _jsx(ChevronDown, { className: `w-4 h-4 transition-transform duration-200 ${openGroups[idx] ? "rotate-180" : ""}` })] }), _jsx(Ul, { className: `lg:hidden overflow-hidden transition-all duration-200 ${openGroups[idx] ? "max-h-96 py-3" : "max-h-0"} space-y-2.5`, children: group.links.map((link) => (_jsx(Li, { children: _jsx(Link, { href: link.href, className: "text-sm text-zinc-500 dark:text-zinc-400 hover:text-primary dark:hover:text-secondary transition-colors", children: link.label }) }, link.href))) }), _jsxs(Div, { className: "hidden lg:block", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 mb-3", children: group.heading }), _jsx(Ul, { className: "space-y-2.5", children: group.links.map((link) => (_jsx(Li, { children: _jsx(Link, { href: link.href, className: "text-sm text-zinc-500 dark:text-zinc-400 hover:text-primary dark:hover:text-secondary transition-colors", children: link.label }) }, link.href))) })] })] }, idx))) })] }), _jsxs(Div, { className: "mt-10 pt-6 border-t border-zinc-200 dark:border-slate-800 flex flex-col sm:flex-row items-center justify-between gap-3 text-xs text-zinc-600 dark:text-zinc-400", children: [_jsx(Text, { className: "text-xs text-zinc-600 dark:text-zinc-400", children: copyrightText }), bottomLinks.length > 0 && (_jsx("nav", { "aria-label": "Site utilities", children: _jsx(Ul, { className: "flex flex-wrap items-center gap-x-4 gap-y-1 justify-center", children: bottomLinks.map((link) => (_jsx(Li, { children: _jsx(Link, { href: link.href, className: "text-xs text-zinc-500 dark:text-zinc-400 hover:text-primary dark:hover:text-secondary transition-colors underline-offset-2 hover:underline", children: link.label }) }, link.href))) }) })), madeInText && (_jsx(Text, { className: "text-xs text-zinc-600 dark:text-zinc-400", children: madeInText }))] })] })] }));
|
|
14
14
|
}
|
|
@@ -57,7 +57,7 @@ export function ListingLayout({ headerSlot, statusTabsSlot, filterContent, filte
|
|
|
57
57
|
.filter(Boolean)
|
|
58
58
|
.join(" "), children: [headerSlot, statusTabsSlot && (_jsx(Div, { className: "overflow-x-auto touch-pan-x -mx-4 px-4 md:-mx-6 md:px-6 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: statusTabsSlot })), _jsxs(Div, { className: [
|
|
59
59
|
"sticky z-20 -mx-4 px-4 md:-mx-6 md:px-6",
|
|
60
|
-
|
|
60
|
+
"top-[var(--header-height,0px)]",
|
|
61
61
|
"bg-white/80 dark:bg-slate-950/80 backdrop-blur-md",
|
|
62
62
|
"border-b border-zinc-200/70 dark:border-slate-800/70",
|
|
63
63
|
"shadow-[0_1px_3px_rgba(0,0,0,0.04)] dark:shadow-[0_1px_3px_rgba(0,0,0,0.2)]",
|
|
@@ -80,7 +80,7 @@ export function ListingLayout({ headerSlot, statusTabsSlot, filterContent, filte
|
|
|
80
80
|
: "",
|
|
81
81
|
].join(" "), children: [l.filtersTitle, filterActiveCount > 0 && (_jsx(Span, { className: "inline-flex items-center justify-center w-4 h-4 text-[10px] font-bold rounded-full bg-primary text-white", children: filterActiveCount }))] })), searchSlot && _jsx(Div, { className: "flex-1 min-w-0", children: searchSlot })] }), (sortSlot || viewToggleSlot || actionsSlot) && (_jsx(Div, { className: "flex items-stretch min-h-[44px] gap-2 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: _jsxs(Row, { className: "gap-2 flex-shrink-0 pb-px", children: [sortSlot, viewToggleSlot, actionsSlot] }) }))] }), selectedCount > 0 && bulkActionBarSlot && (_jsx(Div, { className: "hidden md:block pt-2 mt-2 border-t border-zinc-100 dark:border-slate-800", children: bulkActionBarSlot }))] }), _jsxs(Div, { className: "flex gap-4 lg:gap-6 items-start", children: [hasFilter && (_jsx(Aside, { "aria-label": panelTitle, className: [
|
|
82
82
|
"hidden lg:block flex-shrink-0 self-start",
|
|
83
|
-
|
|
83
|
+
"sticky top-[var(--header-height,0px)]",
|
|
84
84
|
"transition-all duration-200 ease-in-out overflow-hidden",
|
|
85
85
|
sidebarOpen
|
|
86
86
|
? "w-60 xl:w-64 2xl:w-72 opacity-100"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
export interface MainNavbarItem {
|
|
2
3
|
/** Unique key used for filtering */
|
|
3
4
|
key: string;
|
|
@@ -15,18 +16,9 @@ export interface MainNavbarProps {
|
|
|
15
16
|
hiddenNavItems?: string[];
|
|
16
17
|
/** When true, renders the navbar inline instead of sticky */
|
|
17
18
|
inline?: boolean;
|
|
19
|
+
/** Whether a dashboard section has registered a secondary nav drawer. */
|
|
20
|
+
hasDashboardNav?: boolean;
|
|
21
|
+
/** Callback to toggle the dashboard nav drawer (already closes the public sidebar first). */
|
|
22
|
+
onToggleDashboardNav?: () => void;
|
|
18
23
|
}
|
|
19
|
-
|
|
20
|
-
* MainNavbar — horizontal desktop navigation bar.
|
|
21
|
-
*
|
|
22
|
-
* Accepts pre-translated nav items from the consumer config and delegates
|
|
23
|
-
* rendering to the generic NavbarLayout primitive.
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```tsx
|
|
27
|
-
* const t = useTranslations("nav");
|
|
28
|
-
* const items = MAIN_NAV_ITEMS.map(item => ({ ...item, label: t(item.key) }));
|
|
29
|
-
* <MainNavbar navItems={items} />
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export declare function MainNavbar({ navItems, hiddenNavItems, inline, }: MainNavbarProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export declare function MainNavbar({ navItems, hiddenNavItems, inline, hasDashboardNav, onToggleDashboardNav, }: MainNavbarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,21 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { usePathname } from "next/navigation";
|
|
4
4
|
import { NavbarLayout } from "./NavbarLayout";
|
|
5
|
-
|
|
6
|
-
* MainNavbar — horizontal desktop navigation bar.
|
|
7
|
-
*
|
|
8
|
-
* Accepts pre-translated nav items from the consumer config and delegates
|
|
9
|
-
* rendering to the generic NavbarLayout primitive.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```tsx
|
|
13
|
-
* const t = useTranslations("nav");
|
|
14
|
-
* const items = MAIN_NAV_ITEMS.map(item => ({ ...item, label: t(item.key) }));
|
|
15
|
-
* <MainNavbar navItems={items} />
|
|
16
|
-
* ```
|
|
17
|
-
*/
|
|
18
|
-
export function MainNavbar({ navItems, hiddenNavItems = [], inline = false, }) {
|
|
5
|
+
export function MainNavbar({ navItems, hiddenNavItems = [], inline = false, hasDashboardNav = false, onToggleDashboardNav, }) {
|
|
19
6
|
const pathname = usePathname();
|
|
20
7
|
const items = navItems
|
|
21
8
|
.filter((item) => !hiddenNavItems.includes(item.key))
|
|
@@ -25,5 +12,6 @@ export function MainNavbar({ navItems, hiddenNavItems = [], inline = false, }) {
|
|
|
25
12
|
icon: item.icon,
|
|
26
13
|
highlighted: item.highlighted,
|
|
27
14
|
}));
|
|
28
|
-
|
|
15
|
+
const dashboardToggle = hasDashboardNav && onToggleDashboardNav ? (_jsx("button", { type: "button", onClick: onToggleDashboardNav, "aria-label": "Toggle dashboard navigation", className: "flex items-center justify-center w-8 h-8 rounded-lg text-zinc-500 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-slate-800 hover:text-zinc-800 dark:hover:text-zinc-100 transition-colors", children: _jsxs("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: [_jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 5a2 2 0 012-2h14a2 2 0 012 2v14a2 2 0 01-2 2H5a2 2 0 01-2-2V5z" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 3v18" })] }) })) : undefined;
|
|
16
|
+
return (_jsx(NavbarLayout, { items: items, activeHref: pathname, inline: inline, rightSlot: dashboardToggle }));
|
|
29
17
|
}
|
|
@@ -14,7 +14,7 @@ export function NavItem({ href, label, icon, isActive = false, variant = "horizo
|
|
|
14
14
|
className,
|
|
15
15
|
]
|
|
16
16
|
.filter(Boolean)
|
|
17
|
-
.join(" "), children: [isActive && (_jsx(Span, { className: "absolute inset-0 rounded-t-xl bg-gradient-to-b from-primary/
|
|
17
|
+
.join(" "), children: [isActive && (_jsx(Span, { className: "absolute inset-0 rounded-t-xl bg-gradient-to-b from-primary/20 dark:from-secondary/25 to-transparent pointer-events-none", "aria-hidden": true })), _jsx(Row, { className: ["relative", iconClassName].join(" "), children: icon }), _jsx(Span, { className: ["relative whitespace-nowrap", labelClassName].join(" "), children: label })] }));
|
|
18
18
|
}
|
|
19
19
|
if (highlighted) {
|
|
20
20
|
return (_jsxs(Link, { href: href, className: [
|
|
@@ -17,6 +17,8 @@ export interface NavbarLayoutProps {
|
|
|
17
17
|
inline?: boolean;
|
|
18
18
|
/** Render a custom nav item — defaults to an <a> anchor link. */
|
|
19
19
|
renderItem?: (item: NavbarLayoutItem, isActive: boolean) => React.ReactNode;
|
|
20
|
+
/** Optional slot rendered at the far right of the navbar row. */
|
|
21
|
+
rightSlot?: React.ReactNode;
|
|
20
22
|
}
|
|
21
23
|
/**
|
|
22
24
|
* NavbarLayout — generic horizontal navigation bar shell.
|
|
@@ -24,4 +26,4 @@ export interface NavbarLayoutProps {
|
|
|
24
26
|
* Zero domain imports. Receives all navigation items and the current
|
|
25
27
|
* active href as props. Hidden on mobile (visible md+).
|
|
26
28
|
*/
|
|
27
|
-
export declare function NavbarLayout({ items, activeHref, id, ariaLabel, inline, renderItem, }: NavbarLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
export declare function NavbarLayout({ items, activeHref, id, ariaLabel, inline, renderItem, rightSlot, }: NavbarLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,10 +3,10 @@ import Link from "next/link";
|
|
|
3
3
|
import { Div, Li, Nav, Span, Ul } from "../../ui";
|
|
4
4
|
function DefaultNavItem({ item, isActive, }) {
|
|
5
5
|
const activeClasses = item.highlighted
|
|
6
|
-
? "border border-primary-400/40 dark:border-secondary-400/30 text-primary-700 dark:text-secondary-400 bg-primary-50/80 dark:bg-secondary-900/30 px-3"
|
|
6
|
+
? "border border-primary-400/40 dark:border-secondary-400/30 text-primary-700 dark:text-secondary-400 bg-primary-50/80 dark:bg-secondary-900/30 px-3 transition-colors duration-150"
|
|
7
7
|
: isActive
|
|
8
|
-
? "bg-primary-50 dark:bg-secondary-900/
|
|
9
|
-
: "text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-slate-800 hover:text-zinc-950 dark:hover:text-white transition-colors px-3";
|
|
8
|
+
? "bg-primary-50 dark:bg-secondary-900/30 text-primary-800 dark:text-secondary-200 font-semibold px-3 border-b-2 border-primary-500 dark:border-secondary-400 rounded-none pb-[6px] transition-colors duration-150"
|
|
9
|
+
: "text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-slate-800 hover:text-zinc-950 dark:hover:text-white transition-colors duration-150 px-3";
|
|
10
10
|
return (_jsxs(Link, { href: item.href, "aria-current": isActive ? "page" : undefined, className: `flex items-center gap-1.5 py-2 text-sm rounded-lg font-medium transition-colors duration-150 ${activeClasses}`, children: [item.icon, _jsx(Span, { children: item.label })] }));
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
@@ -15,9 +15,9 @@ function DefaultNavItem({ item, isActive, }) {
|
|
|
15
15
|
* Zero domain imports. Receives all navigation items and the current
|
|
16
16
|
* active href as props. Hidden on mobile (visible md+).
|
|
17
17
|
*/
|
|
18
|
-
export function NavbarLayout({ items, activeHref, id = "main-navbar", ariaLabel = "Main navigation", inline = false, renderItem, }) {
|
|
18
|
+
export function NavbarLayout({ items, activeHref, id = "main-navbar", ariaLabel = "Main navigation", inline = false, renderItem, rightSlot, }) {
|
|
19
19
|
if (inline) {
|
|
20
20
|
return (_jsx(Ul, { "aria-label": ariaLabel, className: "hidden xl:flex items-center gap-0.5 xl:gap-1", children: items.map((item) => (_jsx(Li, { children: renderItem ? (renderItem(item, activeHref === item.href)) : (_jsx(DefaultNavItem, { item: item, isActive: activeHref === item.href })) }, item.href))) }));
|
|
21
21
|
}
|
|
22
|
-
return (_jsx(Nav, { id: id, "aria-label": ariaLabel, className: "hidden lg:block bg-white/95 dark:bg-slate-950/95 backdrop-blur-md border-b border-zinc-100 dark:border-slate-800", children:
|
|
22
|
+
return (_jsx(Nav, { id: id, "aria-label": ariaLabel, className: "hidden lg:block bg-white/95 dark:bg-slate-950/95 backdrop-blur-md border-b border-zinc-100 dark:border-slate-800", children: _jsxs(Div, { className: "container mx-auto px-4 sm:px-6 lg:px-8 max-w-[1920px] flex items-center h-10", children: [_jsx(Ul, { className: "flex items-center gap-0.5 lg:gap-1 flex-1", children: items.map((item) => (_jsx(Li, { children: renderItem ? (renderItem(item, activeHref === item.href)) : (_jsx(DefaultNavItem, { item: item, isActive: activeHref === item.href })) }, item.href))) }), rightSlot && _jsx(Div, { className: "shrink-0 ml-2", children: rightSlot })] }) }));
|
|
23
23
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { TitleBarLayoutProps } from "./TitleBarLayout";
|
|
2
|
-
export interface TitleBarProps extends Omit<TitleBarLayoutProps, "cartCount" | "hasDashboardNav" | "onToggleDashboardNav"> {
|
|
2
|
+
export interface TitleBarProps extends Omit<TitleBarLayoutProps, "cartCount" | "wishlistCount" | "hasDashboardNav" | "onToggleDashboardNav"> {
|
|
3
|
+
/** Auth UID of the current user — used for wishlist merge-on-login and sync. */
|
|
4
|
+
userId?: string | null;
|
|
3
5
|
/**
|
|
4
6
|
* When true, hides the dashboard nav PanelLeft button so that nested
|
|
5
7
|
* admin/seller/user layouts can own their sidebar controls exclusively.
|
|
@@ -17,4 +19,4 @@ export interface TitleBarProps extends Omit<TitleBarLayoutProps, "cartCount" | "
|
|
|
17
19
|
* Wrap with `DashboardNavProvider` at the app root to enable the
|
|
18
20
|
* dashboard nav button in nested admin/seller/user routes.
|
|
19
21
|
*/
|
|
20
|
-
export declare function TitleBar({ suppressDashboardNav, onBeforeToggleDashboardNav, ...rest }: TitleBarProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export declare function TitleBar({ suppressDashboardNav, onBeforeToggleDashboardNav, userId, ...rest }: TitleBarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useCartCount } from "../cart/hooks/useCartCount";
|
|
3
|
+
import { useWishlistCount } from "../wishlist/hooks/useWishlistCount";
|
|
3
4
|
import { useDashboardNav } from "./DashboardNavContext";
|
|
4
5
|
import { TitleBarLayout } from "./TitleBarLayout";
|
|
5
6
|
/**
|
|
@@ -11,10 +12,11 @@ import { TitleBarLayout } from "./TitleBarLayout";
|
|
|
11
12
|
* Wrap with `DashboardNavProvider` at the app root to enable the
|
|
12
13
|
* dashboard nav button in nested admin/seller/user routes.
|
|
13
14
|
*/
|
|
14
|
-
export function TitleBar({ suppressDashboardNav, onBeforeToggleDashboardNav, ...rest }) {
|
|
15
|
-
const cartCount = useCartCount();
|
|
15
|
+
export function TitleBar({ suppressDashboardNav, onBeforeToggleDashboardNav, userId, ...rest }) {
|
|
16
|
+
const cartCount = useCartCount(!!rest.user);
|
|
17
|
+
const wishlistCount = useWishlistCount(userId);
|
|
16
18
|
const { hasNav: hasDashboardNav, toggleNav: toggleDashboardNav } = useDashboardNav();
|
|
17
|
-
return (_jsx(TitleBarLayout, { ...rest, cartCount: cartCount, hasDashboardNav: suppressDashboardNav ? false : hasDashboardNav, onToggleDashboardNav: suppressDashboardNav
|
|
19
|
+
return (_jsx(TitleBarLayout, { ...rest, cartCount: cartCount, wishlistCount: wishlistCount, hasDashboardNav: suppressDashboardNav ? false : hasDashboardNav, onToggleDashboardNav: suppressDashboardNav
|
|
18
20
|
? undefined
|
|
19
21
|
: () => {
|
|
20
22
|
onBeforeToggleDashboardNav?.();
|
|
@@ -18,6 +18,8 @@ export interface TitleBarLayoutProps {
|
|
|
18
18
|
promotionsHref?: string;
|
|
19
19
|
/** Href for the compare page/drawer. When provided, renders a Compare icon button. */
|
|
20
20
|
compareHref?: string;
|
|
21
|
+
wishlistHref?: string;
|
|
22
|
+
wishlistCount?: number;
|
|
21
23
|
cartHref?: string;
|
|
22
24
|
cartCount?: number;
|
|
23
25
|
profileHref?: string;
|
|
@@ -47,4 +49,4 @@ export interface TitleBarLayoutProps {
|
|
|
47
49
|
* Receives all domain data as props — zero domain imports.
|
|
48
50
|
* Domain shell reads useAuth() and SITE_CONFIG and passes values in.
|
|
49
51
|
*/
|
|
50
|
-
export declare function TitleBarLayout({ onToggleSidebar, sidebarOpen, onSearchToggle, searchOpen, brandName, brandShortName, logoHref, promotionsHref, compareHref, cartHref, cartCount, profileHref, user, notificationSlot, devSlot, navSlot, promoStripText, isDark, onToggleTheme, hasDashboardNav, onToggleDashboardNav, hideSidebarToggle, id, className, }: TitleBarLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
52
|
+
export declare function TitleBarLayout({ onToggleSidebar, sidebarOpen, onSearchToggle, searchOpen, brandName, brandShortName, logoHref, promotionsHref, compareHref, wishlistHref, wishlistCount, cartHref, cartCount, profileHref, user, notificationSlot, devSlot, navSlot, promoStripText, isDark, onToggleTheme, hasDashboardNav, onToggleDashboardNav, hideSidebarToggle, id, className, }: TitleBarLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -8,9 +8,9 @@ import { BlockHeader, Button, Div, Row, Span } from "../../ui";
|
|
|
8
8
|
* Receives all domain data as props — zero domain imports.
|
|
9
9
|
* Domain shell reads useAuth() and SITE_CONFIG and passes values in.
|
|
10
10
|
*/
|
|
11
|
-
export function TitleBarLayout({ onToggleSidebar, sidebarOpen, onSearchToggle, searchOpen, brandName, brandShortName, logoHref, promotionsHref, compareHref, cartHref, cartCount = 0, profileHref, user, notificationSlot, devSlot, navSlot, promoStripText, isDark = false, onToggleTheme, hasDashboardNav = false, onToggleDashboardNav, hideSidebarToggle = false, id = "titlebar", className = "", }) {
|
|
11
|
+
export function TitleBarLayout({ onToggleSidebar, sidebarOpen, onSearchToggle, searchOpen, brandName, brandShortName, logoHref, promotionsHref, compareHref, wishlistHref, wishlistCount = 0, cartHref, cartCount = 0, profileHref, user, notificationSlot, devSlot, navSlot, promoStripText, isDark = false, onToggleTheme, hasDashboardNav = false, onToggleDashboardNav, hideSidebarToggle = false, id = "titlebar", className = "", }) {
|
|
12
12
|
void searchOpen;
|
|
13
|
-
return (_jsxs(BlockHeader, { id: id, className: `sticky top-0 z-50 bg-white/95 dark:bg-slate-950/95 backdrop-blur-md border-b border-zinc-100 dark:border-slate-800 shadow-sm ${className}`, children: [promoStripText && (_jsx(Div, { className: "bg-gradient-to-r from-primary-700 to-
|
|
13
|
+
return (_jsxs(BlockHeader, { id: id, className: `sticky top-0 z-50 bg-white/95 dark:bg-slate-950/95 backdrop-blur-md border-b border-zinc-100 dark:border-slate-800 shadow-sm ${className}`, children: [promoStripText && (_jsx(Div, { className: "bg-gradient-to-r from-primary-700 to-secondary-600 dark:from-primary-700 dark:to-cobalt-700 text-white text-xs py-1 text-center font-medium", children: promoStripText })), _jsx(Div, { className: "container mx-auto px-4 sm:px-6 lg:px-8 max-w-[1920px]", children: _jsxs(Row, { justify: "between", gap: "none", className: "h-14", children: [_jsx(Row, { gap: "3", children: _jsx(Link, { href: logoHref, className: "font-bold text-xl tracking-tight text-zinc-900 dark:text-zinc-50 hover:text-primary dark:hover:text-secondary transition-colors", children: brandShortName ? (_jsxs(_Fragment, { children: [_jsx(Span, { className: "md:hidden", children: brandShortName }), _jsx(Span, { className: "hidden md:inline", children: brandName })] })) : (brandName) }) }), navSlot && _jsx(Div, { className: "hidden md:flex", children: navSlot }), _jsxs(Row, { gap: "xs", children: [promotionsHref && (_jsxs(Link, { href: promotionsHref, "aria-label": "Today's deals", className: "hidden lg:flex items-center gap-1 px-3 py-1 rounded-full text-xs font-bold bg-primary-100 text-primary-700 dark:bg-secondary-900/40 dark:text-secondary-400 hover:bg-primary-200 dark:hover:bg-secondary-900/60 transition-colors border border-primary-200/60 dark:border-secondary-700/40", children: [_jsx("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: _jsx("path", { d: "M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.37.86.58 1.41.58.55 0 1.05-.21 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z" }) }), "Today's Deals"] })), compareHref && (_jsx(Link, { href: compareHref, "aria-label": "Compare items", className: "hidden lg:flex items-center justify-center w-9 h-9 rounded-lg text-zinc-600 dark:text-zinc-400 hover:bg-primary-50 hover:text-primary-700 dark:hover:bg-slate-800 dark:hover:text-secondary-400 transition-colors", children: _jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" }) }) })), _jsx(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": "Search", onClick: onSearchToggle, className: "flex items-center justify-center w-9 h-9 rounded-lg text-zinc-600 dark:text-zinc-400 hover:bg-primary-50 hover:text-primary-700 dark:hover:bg-slate-800 dark:hover:text-secondary-400 transition-colors", children: _jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-4.35-4.35M17 11A6 6 0 1 1 5 11a6 6 0 0 1 12 0z" }) }) }), notificationSlot, devSlot, onToggleTheme && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": isDark ? "Switch to light mode" : "Switch to dark mode", onClick: onToggleTheme, className: "flex items-center justify-center w-9 h-9 rounded-lg text-zinc-600 dark:text-zinc-400 hover:bg-primary-50 hover:text-primary-700 dark:hover:bg-slate-800 dark:hover:text-secondary-400 transition-colors", children: isDark ? (_jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 3v1m0 16v1m8.66-9h-1M4.34 12h-1m15.07-6.07-.71.71M6.34 17.66l-.71.71m12.73 0-.71-.71M6.34 6.34l-.71-.71M12 5a7 7 0 1 0 0 14A7 7 0 0 0 12 5z" }) })) : (_jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 12.79A9 9 0 1 1 11.21 3a7 7 0 1 0 9.79 9.79z" }) })) })), wishlistHref && (_jsxs(Link, { href: wishlistHref, "aria-label": `Wishlist${wishlistCount > 0 ? `, ${wishlistCount} items` : ""}`, className: "relative flex items-center justify-center w-9 h-9 rounded-lg text-zinc-600 dark:text-zinc-400 hover:bg-primary-50 hover:text-primary-700 dark:hover:bg-slate-800 dark:hover:text-secondary-400 transition-colors", children: [_jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4.318 6.318a4.5 4.5 0 0 0 0 6.364L12 20.364l7.682-7.682a4.5 4.5 0 0 0-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 0 0-6.364 0z" }) }), wishlistCount > 0 && (_jsx(Span, { className: "absolute -top-0.5 -right-0.5 flex items-center justify-center w-4 h-4 rounded-full bg-red-500 text-white text-[10px] font-bold leading-none", children: wishlistCount > 9 ? "9+" : wishlistCount }))] })), cartHref && (_jsxs(Link, { href: cartHref, "aria-label": `Cart${cartCount > 0 ? `, ${cartCount} items` : ""}`, className: "relative flex items-center justify-center w-9 h-9 rounded-lg text-zinc-600 dark:text-zinc-400 hover:bg-primary-50 hover:text-primary-700 dark:hover:bg-slate-800 dark:hover:text-secondary-400 transition-colors", children: [_jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 0 0-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 0 0-16.536-1.84M7.5 14.25 5.106 5.272M6 20.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm12.75 0a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0z" }) }), cartCount > 0 && (_jsx(Span, { className: "absolute -top-0.5 -right-0.5 flex items-center justify-center w-4 h-4 rounded-full bg-red-500 text-white text-[10px] font-bold leading-none", children: cartCount > 9 ? "9+" : cartCount }))] })), !hideSidebarToggle && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": sidebarOpen ? "Close menu" : "Open menu", "aria-expanded": sidebarOpen, "aria-controls": "secondary-sidebar", onClick: onToggleSidebar, className: "flex items-center justify-center w-9 h-9 rounded-lg text-zinc-600 dark:text-zinc-400 hover:bg-primary-50 hover:text-primary-700 dark:hover:bg-slate-800 dark:hover:text-secondary-400 transition-colors", children: _jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: sidebarOpen ? (_jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" })) : (_jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 12h16M4 18h16" })) }) })), profileHref && (_jsx(Link, { href: profileHref, "aria-label": user
|
|
14
14
|
? `Profile — ${user.displayName ?? user.email}`
|
|
15
15
|
: "Sign in", className: "flex items-center justify-center w-9 h-9 rounded-lg text-zinc-600 dark:text-zinc-400 hover:bg-primary-50 hover:text-primary-700 dark:hover:bg-slate-800 dark:hover:text-secondary-400 transition-colors", children: user?.photoURL ? (_jsx(Image, { src: user.photoURL, alt: user.displayName ?? "Profile", width: 28, height: 28, className: "w-7 h-7 rounded-full object-cover" })) : (_jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0zM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632z" }) })) }))] })] }) })] }));
|
|
16
16
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { NavbarLayout } from "./NavbarLayout";
|
|
2
2
|
export type { NavbarLayoutProps, NavbarLayoutItem } from "./NavbarLayout";
|
|
3
3
|
export { FooterLayout } from "./FooterLayout";
|
|
4
|
-
export type { FooterLayoutProps, FooterLinkGroup, FooterSocialLink, TrustBarItem, } from "./FooterLayout";
|
|
4
|
+
export type { FooterLayoutProps, FooterLinkGroup, FooterSocialLink, FooterBottomLink, TrustBarItem, } from "./FooterLayout";
|
|
5
5
|
export { SidebarLayout } from "./SidebarLayout";
|
|
6
6
|
export type { SidebarLayoutProps } from "./SidebarLayout";
|
|
7
7
|
export { BottomNavLayout } from "./BottomNavLayout";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface MediaPickerModalProps {
|
|
2
|
+
isOpen: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
/** Called with the selected media URL (proxy path or external URL). */
|
|
5
|
+
onSelect: (url: string) => void;
|
|
6
|
+
/** Accepted MIME types for file upload. Defaults to image/*. */
|
|
7
|
+
accept?: string;
|
|
8
|
+
/** Max file size in MB for upload tab. Defaults to 10. */
|
|
9
|
+
maxSizeMB?: number;
|
|
10
|
+
/** Storage path prefix for uploaded files. Defaults to "media". */
|
|
11
|
+
uploadPath?: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* MediaPickerModal — pick or upload a media file for use in a form field.
|
|
16
|
+
*
|
|
17
|
+
* Two tabs:
|
|
18
|
+
* - Upload: drag/drop or click to upload a new file → "Use this file" button
|
|
19
|
+
* - URL: paste an external image/video URL directly
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* <MediaPickerModal
|
|
24
|
+
* isOpen={open}
|
|
25
|
+
* onClose={() => setOpen(false)}
|
|
26
|
+
* onSelect={(url) => form.setValue("imageUrl", url)}
|
|
27
|
+
* />
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function MediaPickerModal({ isOpen, onClose, onSelect, accept, maxSizeMB, uploadPath, title, }: MediaPickerModalProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useCallback } from "react";
|
|
4
|
+
import { Modal } from "../../ui/components/Modal";
|
|
5
|
+
import { Button, Input, Label, Row, Stack, Text, Alert } from "../../ui";
|
|
6
|
+
import { MediaUploadField } from "./upload/MediaUploadField";
|
|
7
|
+
import { useMediaUpload, useMediaCleanup } from "./index";
|
|
8
|
+
/**
|
|
9
|
+
* MediaPickerModal — pick or upload a media file for use in a form field.
|
|
10
|
+
*
|
|
11
|
+
* Two tabs:
|
|
12
|
+
* - Upload: drag/drop or click to upload a new file → "Use this file" button
|
|
13
|
+
* - URL: paste an external image/video URL directly
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <MediaPickerModal
|
|
18
|
+
* isOpen={open}
|
|
19
|
+
* onClose={() => setOpen(false)}
|
|
20
|
+
* onSelect={(url) => form.setValue("imageUrl", url)}
|
|
21
|
+
* />
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export function MediaPickerModal({ isOpen, onClose, onSelect, accept = "image/*", maxSizeMB = 10, uploadPath = "media", title = "Pick Media", }) {
|
|
25
|
+
const [tab, setTab] = useState("upload");
|
|
26
|
+
const [uploadedUrl, setUploadedUrl] = useState("");
|
|
27
|
+
const [externalUrl, setExternalUrl] = useState("");
|
|
28
|
+
const [urlError, setUrlError] = useState("");
|
|
29
|
+
const { upload } = useMediaUpload();
|
|
30
|
+
const { cleanup } = useMediaCleanup();
|
|
31
|
+
const handleUpload = useCallback((file) => upload(file, uploadPath, true), [upload, uploadPath]);
|
|
32
|
+
const handleAbort = useCallback((urls) => { void cleanup(urls); }, [cleanup]);
|
|
33
|
+
function handleUseUpload() {
|
|
34
|
+
if (!uploadedUrl)
|
|
35
|
+
return;
|
|
36
|
+
onSelect(uploadedUrl);
|
|
37
|
+
resetAndClose();
|
|
38
|
+
}
|
|
39
|
+
function handleUseExternal() {
|
|
40
|
+
const trimmed = externalUrl.trim();
|
|
41
|
+
if (!trimmed) {
|
|
42
|
+
setUrlError("Please enter a URL.");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
new URL(trimmed);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
setUrlError("Enter a valid URL starting with https://");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
onSelect(trimmed);
|
|
53
|
+
resetAndClose();
|
|
54
|
+
}
|
|
55
|
+
function resetAndClose() {
|
|
56
|
+
setUploadedUrl("");
|
|
57
|
+
setExternalUrl("");
|
|
58
|
+
setUrlError("");
|
|
59
|
+
setTab("upload");
|
|
60
|
+
onClose();
|
|
61
|
+
}
|
|
62
|
+
const tabBtnClass = (active) => [
|
|
63
|
+
"appkit-media-picker__tab-btn",
|
|
64
|
+
active ? "appkit-media-picker__tab-btn--active" : "",
|
|
65
|
+
]
|
|
66
|
+
.filter(Boolean)
|
|
67
|
+
.join(" ");
|
|
68
|
+
return (_jsx(Modal, { isOpen: isOpen, onClose: resetAndClose, title: title, size: "lg", actions: _jsxs(Row, { gap: "sm", justify: "end", children: [_jsx(Button, { variant: "ghost", onClick: resetAndClose, children: "Cancel" }), tab === "upload" ? (_jsx(Button, { variant: "primary", onClick: handleUseUpload, disabled: !uploadedUrl, children: "Use this file" })) : (_jsx(Button, { variant: "primary", onClick: handleUseExternal, disabled: !externalUrl.trim(), children: "Use this URL" }))] }), children: _jsxs(Stack, { gap: "md", children: [_jsxs(Row, { gap: "none", className: "appkit-media-picker__tabs", children: [_jsx("button", { type: "button", className: tabBtnClass(tab === "upload"), onClick: () => setTab("upload"), children: "Upload file" }), _jsx("button", { type: "button", className: tabBtnClass(tab === "url"), onClick: () => setTab("url"), children: "External URL" })] }), tab === "upload" && (_jsx(MediaUploadField, { label: "File", value: uploadedUrl, onChange: setUploadedUrl, onUpload: handleUpload, accept: accept, maxSizeMB: maxSizeMB, onAbort: handleAbort })), tab === "url" && (_jsxs(Stack, { gap: "sm", children: [_jsx(Label, { htmlFor: "media-picker-url", children: "Image or video URL" }), _jsx(Input, { id: "media-picker-url", value: externalUrl, onChange: (e) => {
|
|
69
|
+
setExternalUrl(e.target.value);
|
|
70
|
+
setUrlError("");
|
|
71
|
+
}, placeholder: "https://example.com/image.jpg" }), urlError && _jsx(Alert, { variant: "error", children: urlError }), _jsx(Text, { size: "sm", color: "muted", children: "External URLs are stored as-is and are not watermarked." })] }))] }) }));
|
|
72
|
+
}
|
|
@@ -10,6 +10,8 @@ export { MediaSlider } from "./components/MediaSlider";
|
|
|
10
10
|
export type { MediaSliderProps } from "./components/MediaSlider";
|
|
11
11
|
export { useMediaUpload, useMediaAbort, useMediaCrop, useMediaTrim, useMediaCleanup, } from "./hooks/useMedia";
|
|
12
12
|
export type { MediaUploadResult, MediaCropInput, MediaTrimInput, } from "./hooks/useMedia";
|
|
13
|
+
export { MediaPickerModal } from "./MediaPickerModal";
|
|
14
|
+
export type { MediaPickerModalProps } from "./MediaPickerModal";
|
|
13
15
|
export { ImageCropModal } from "./modals/ImageCropModal";
|
|
14
16
|
export type { ImageCropData, ImageCropModalProps, } from "./modals/ImageCropModal";
|
|
15
17
|
export { VideoTrimModal } from "./modals/VideoTrimModal";
|
|
@@ -23,7 +25,7 @@ export type { MediaUploadFieldProps } from "./upload/MediaUploadField";
|
|
|
23
25
|
export { MediaUploadList } from "./upload/MediaUploadList";
|
|
24
26
|
export type { MediaUploadListProps } from "./upload/MediaUploadList";
|
|
25
27
|
export { coerceMediaField, coerceMediaFieldArray, getMediaUrl, inferMediaTypeFromMime, mediaFieldSchema, } from "./types/index";
|
|
26
|
-
export type { MediaField, MediaFieldInput, MediaFieldType, } from "./types/index";
|
|
28
|
+
export type { MediaField, MediaFieldInput, MediaFieldType, MediaSource, } from "./types/index";
|
|
27
29
|
export { default as CameraCapture } from "./upload/CameraCapture";
|
|
28
30
|
export type { CameraCaptureProps } from "./upload/CameraCapture";
|
|
29
31
|
export { AvatarUpload } from "./AvatarUpload";
|
|
@@ -9,6 +9,7 @@ export { MediaSlider } from "./components/MediaSlider";
|
|
|
9
9
|
// Hooks
|
|
10
10
|
export { useMediaUpload, useMediaAbort, useMediaCrop, useMediaTrim, useMediaCleanup, } from "./hooks/useMedia";
|
|
11
11
|
// Modals
|
|
12
|
+
export { MediaPickerModal } from "./MediaPickerModal";
|
|
12
13
|
export { ImageCropModal } from "./modals/ImageCropModal";
|
|
13
14
|
export { VideoTrimModal } from "./modals/VideoTrimModal";
|
|
14
15
|
export { VideoThumbnailSelector } from "./modals/VideoThumbnailSelector";
|
|
@@ -1,27 +1,39 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export type MediaFieldType = "image" | "video" | "file";
|
|
3
|
+
/** Where the media originates: Firebase Storage upload, YouTube embed, or external URL. */
|
|
4
|
+
export type MediaSource = "upload" | "youtube" | "external";
|
|
3
5
|
export type MediaFieldInput = MediaField | string | null | undefined;
|
|
4
6
|
export interface MediaField {
|
|
5
7
|
url: string;
|
|
6
8
|
type: MediaFieldType;
|
|
7
9
|
alt?: string;
|
|
8
10
|
thumbnailUrl?: string;
|
|
11
|
+
/** Media origin. Omitted / "upload" = Firebase Storage proxy URL. */
|
|
12
|
+
source?: MediaSource;
|
|
13
|
+
/** YouTube video ID. Only set when source === "youtube". */
|
|
14
|
+
youtubeId?: string;
|
|
9
15
|
}
|
|
10
16
|
export declare const mediaFieldSchema: z.ZodObject<{
|
|
11
17
|
url: z.ZodString;
|
|
12
18
|
type: z.ZodEnum<["image", "video", "file"]>;
|
|
13
19
|
alt: z.ZodOptional<z.ZodString>;
|
|
14
20
|
thumbnailUrl: z.ZodOptional<z.ZodString>;
|
|
21
|
+
source: z.ZodOptional<z.ZodEnum<["upload", "youtube", "external"]>>;
|
|
22
|
+
youtubeId: z.ZodOptional<z.ZodString>;
|
|
15
23
|
}, "strip", z.ZodTypeAny, {
|
|
16
24
|
url: string;
|
|
17
25
|
type: "video" | "image" | "file";
|
|
26
|
+
source?: "external" | "upload" | "youtube" | undefined;
|
|
18
27
|
alt?: string | undefined;
|
|
19
28
|
thumbnailUrl?: string | undefined;
|
|
29
|
+
youtubeId?: string | undefined;
|
|
20
30
|
}, {
|
|
21
31
|
url: string;
|
|
22
32
|
type: "video" | "image" | "file";
|
|
33
|
+
source?: "external" | "upload" | "youtube" | undefined;
|
|
23
34
|
alt?: string | undefined;
|
|
24
35
|
thumbnailUrl?: string | undefined;
|
|
36
|
+
youtubeId?: string | undefined;
|
|
25
37
|
}>;
|
|
26
38
|
export declare function coerceMediaField(value: MediaFieldInput, fallbackType?: MediaFieldType): MediaField | null;
|
|
27
39
|
export declare function coerceMediaFieldArray(values: Array<MediaField | string> | null | undefined, fallbackType?: MediaFieldType): MediaField[];
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export const mediaFieldSchema = z.object({
|
|
3
|
-
url: z.string()
|
|
3
|
+
url: z.string(),
|
|
4
4
|
type: z.enum(["image", "video", "file"]),
|
|
5
5
|
alt: z.string().optional(),
|
|
6
|
-
thumbnailUrl: z.string().
|
|
6
|
+
thumbnailUrl: z.string().optional(),
|
|
7
|
+
source: z.enum(["upload", "youtube", "external"]).optional(),
|
|
8
|
+
youtubeId: z.string().optional(),
|
|
7
9
|
});
|
|
8
10
|
export function coerceMediaField(value, fallbackType = "image") {
|
|
9
11
|
if (!value) {
|
|
@@ -14,6 +14,10 @@ export interface MediaUploadFieldProps {
|
|
|
14
14
|
enableTrim?: boolean;
|
|
15
15
|
enableThumbnail?: boolean;
|
|
16
16
|
onThumbnailChange?: (url: string) => void;
|
|
17
|
+
/** Show a "YouTube URL" tab to embed a YouTube video by ID or URL. */
|
|
18
|
+
showYoutube?: boolean;
|
|
19
|
+
/** Show an "External URL" tab to link a third-party image/video URL. */
|
|
20
|
+
showExternal?: boolean;
|
|
17
21
|
/**
|
|
18
22
|
* Called with every URL that was staged (uploaded) but never persisted.
|
|
19
23
|
* The parent form should call `DELETE /api/media?url=…` for each entry.
|
|
@@ -28,4 +32,4 @@ export interface MediaUploadFieldProps {
|
|
|
28
32
|
*/
|
|
29
33
|
isPersisted?: boolean;
|
|
30
34
|
}
|
|
31
|
-
export declare function MediaUploadField({ label, value, onChange, onChangeField, onUpload, accept, maxSizeMB, disabled, helperText, captureSource, captureMode, enableTrim, enableThumbnail, onThumbnailChange, onAbort, onStagedUrlsChange, isPersisted, }: MediaUploadFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
export declare function MediaUploadField({ label, value, onChange, onChangeField, onUpload, accept, maxSizeMB, disabled, helperText, captureSource, captureMode, enableTrim, enableThumbnail, onThumbnailChange, showYoutube, showExternal, onAbort, onStagedUrlsChange, isPersisted, }: MediaUploadFieldProps): import("react/jsx-runtime").JSX.Element;
|