@mohasinac/appkit 2.7.26 → 2.7.30
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/_internal/client/features/classified/ClassifiedDetailView.js +2 -2
- package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +2 -2
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +1 -1
- package/dist/_internal/server/features/checkout/actions.js +42 -35
- package/dist/_internal/server/features/classified/adapters.d.ts +21 -0
- package/dist/_internal/server/features/classified/adapters.js +24 -0
- package/dist/_internal/server/features/classified/index.d.ts +3 -0
- package/dist/_internal/server/features/classified/index.js +3 -0
- package/dist/_internal/server/features/classified/metadata.d.ts +8 -0
- package/dist/_internal/server/features/classified/metadata.js +43 -0
- package/dist/_internal/server/features/classified/og.d.ts +30 -0
- package/dist/_internal/server/features/classified/og.js +76 -0
- package/dist/_internal/server/features/digital-code/adapters.d.ts +21 -0
- package/dist/_internal/server/features/digital-code/adapters.js +29 -0
- package/dist/_internal/server/features/digital-code/index.d.ts +3 -0
- package/dist/_internal/server/features/digital-code/index.js +3 -0
- package/dist/_internal/server/features/digital-code/metadata.d.ts +8 -0
- package/dist/_internal/server/features/digital-code/metadata.js +36 -0
- package/dist/_internal/server/features/digital-code/og.d.ts +27 -0
- package/dist/_internal/server/features/digital-code/og.js +77 -0
- package/dist/_internal/server/features/live/adapters.d.ts +21 -0
- package/dist/_internal/server/features/live/adapters.js +34 -0
- package/dist/_internal/server/features/live/index.d.ts +3 -0
- package/dist/_internal/server/features/live/index.js +3 -0
- package/dist/_internal/server/features/live/metadata.d.ts +8 -0
- package/dist/_internal/server/features/live/metadata.js +39 -0
- package/dist/_internal/server/features/live/og.d.ts +27 -0
- package/dist/_internal/server/features/live/og.js +72 -0
- package/dist/_internal/server/features/promotions/actions.js +4 -3
- package/dist/_internal/server/jobs/core/onOrderCreate.js +19 -16
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +25 -22
- package/dist/_internal/server/jobs/core/onProductWrite.js +48 -58
- package/dist/_internal/shared/actions/action-registry.js +310 -8
- package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
- package/dist/_internal/shared/features/brands/schema.d.ts +5 -5
- package/dist/_internal/shared/features/cart/schema.d.ts +18 -18
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +1 -1
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +38 -38
- package/dist/_internal/shared/features/events/schema.d.ts +8 -8
- package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
- package/dist/_internal/shared/features/products/schema.d.ts +42 -42
- package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
- package/dist/_internal/shared/features/reviews/schema.d.ts +1 -1
- package/dist/_internal/shared/media/limits.js +4 -3
- package/dist/client.d.ts +2 -0
- package/dist/client.js +1 -0
- package/dist/configs/next.js +4 -0
- package/dist/constants/table-keys.d.ts +6 -0
- package/dist/constants/table-keys.js +9 -0
- package/dist/core/hooks/useSyncManager.js +9 -8
- package/dist/features/about/components/FeesView.js +10 -7
- package/dist/features/about/components/HelpPageView.js +10 -1
- package/dist/features/about/components/HowAuctionsWorkView.js +10 -1
- package/dist/features/about/components/HowCheckoutWorksView.js +10 -1
- package/dist/features/about/components/HowOffersWorkView.js +10 -1
- package/dist/features/about/components/HowOrdersWorkView.js +10 -1
- package/dist/features/about/components/HowPayoutsWorkView.js +10 -1
- package/dist/features/about/components/HowPreOrdersWorkView.js +10 -1
- package/dist/features/about/components/HowReviewsWorkView.js +10 -1
- package/dist/features/about/components/PublicProfileView.js +44 -14
- package/dist/features/about/components/SecurityPrivacyView.js +7 -1
- package/dist/features/account/components/AddressesIndexListing.js +2 -2
- package/dist/features/account/components/NotificationBell.js +27 -16
- package/dist/features/account/components/NotificationPreferencesPanel.d.ts +9 -0
- package/dist/features/account/components/NotificationPreferencesPanel.js +91 -0
- package/dist/features/account/components/UserSidebar.js +4 -4
- package/dist/features/account/components/UserSupportView.js +16 -6
- package/dist/features/account/components/index.d.ts +2 -0
- package/dist/features/account/components/index.js +1 -0
- package/dist/features/account/schemas/index.d.ts +4 -4
- package/dist/features/account/types/index.d.ts +34 -0
- package/dist/features/admin/actions/admin-actions.js +4 -3
- package/dist/features/admin/actions/notification-actions.d.ts +24 -22
- package/dist/features/admin/actions/notification-actions.js +122 -22
- package/dist/features/admin/components/AdminAdEditorView.js +29 -15
- package/dist/features/admin/components/AdminAdsView.js +22 -28
- package/dist/features/admin/components/AdminAllEventEntriesView.js +6 -1
- package/dist/features/admin/components/AdminBidsView.js +10 -3
- package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
- package/dist/features/admin/components/AdminBlogView.js +8 -3
- package/dist/features/admin/components/AdminBrandsView.js +7 -2
- package/dist/features/admin/components/AdminBundleEditorView.js +5 -2
- package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
- package/dist/features/admin/components/AdminCarouselView.js +13 -7
- package/dist/features/admin/components/AdminCategoriesView.js +8 -3
- package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
- package/dist/features/admin/components/AdminContactView.js +6 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +8 -2
- package/dist/features/admin/components/AdminCouponsView.js +6 -1
- package/dist/features/admin/components/AdminEmployeeEditorView.js +12 -9
- package/dist/features/admin/components/AdminFaqEditorView.js +2 -2
- package/dist/features/admin/components/AdminFaqsView.js +7 -2
- package/dist/features/admin/components/AdminFeaturesView.js +4 -3
- package/dist/features/admin/components/AdminMediaView.js +9 -8
- package/dist/features/admin/components/AdminNavigationView.js +10 -17
- package/dist/features/admin/components/AdminNewsletterView.js +6 -1
- package/dist/features/admin/components/AdminNotificationsView.js +11 -3
- package/dist/features/admin/components/AdminOrdersView.js +6 -1
- package/dist/features/admin/components/AdminPayoutsView.js +10 -3
- package/dist/features/admin/components/AdminPrizeDrawsView.js +10 -3
- package/dist/features/admin/components/AdminProductsView.js +18 -12
- package/dist/features/admin/components/AdminReviewsView.js +33 -24
- package/dist/features/admin/components/AdminScammerEditorView.js +3 -2
- package/dist/features/admin/components/AdminScammersView.js +28 -26
- package/dist/features/admin/components/AdminSectionsView.js +112 -99
- package/dist/features/admin/components/AdminSessionsView.js +10 -3
- package/dist/features/admin/components/AdminSidebar.js +4 -4
- package/dist/features/admin/components/AdminSiteSettingsView.js +45 -4
- package/dist/features/admin/components/AdminStoresView.js +6 -1
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +0 -1
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketsView.js +32 -34
- package/dist/features/admin/components/AdminTeamView.js +6 -1
- package/dist/features/admin/components/AdminUserEditorView.js +8 -15
- package/dist/features/admin/components/AdminUsersView.js +6 -1
- package/dist/features/admin/components/AdminViewCards.js +4 -3
- package/dist/features/admin/components/DashboardStats.js +2 -2
- package/dist/features/admin/components/DataTable.js +2 -2
- package/dist/features/admin/components/sections/adminSectionsTypes.js +4 -3
- package/dist/features/admin/repository/chat.repository.js +8 -8
- package/dist/features/admin/repository/site-settings.repository.d.ts +1 -0
- package/dist/features/admin/repository/site-settings.repository.js +11 -9
- package/dist/features/admin/schemas/firestore.d.ts +38 -0
- package/dist/features/admin/schemas/firestore.js +15 -0
- package/dist/features/auctions/components/AuctionDetailPageView.js +13 -19
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +18 -9
- package/dist/features/auctions/components/MarketplaceAuctionGrid.js +3 -2
- package/dist/features/auctions/components/index.d.ts +0 -1
- package/dist/features/auctions/components/index.js +0 -1
- package/dist/features/auctions/schemas/index.d.ts +14 -14
- package/dist/features/auth/actions/realtime-token-actions.js +19 -4
- package/dist/features/auth/components/RegisterForm.js +8 -4
- package/dist/features/auth/consent-otp.d.ts +2 -0
- package/dist/features/auth/consent-otp.js +8 -0
- package/dist/features/auth/schemas/firestore.d.ts +2 -0
- package/dist/features/auth/schemas/firestore.js +18 -25
- package/dist/features/auth/schemas/index.d.ts +2 -2
- package/dist/features/before-after/api/[id]/route.js +8 -6
- package/dist/features/before-after/schemas/index.d.ts +2 -2
- package/dist/features/blog/actions/blog-actions.d.ts +3 -3
- package/dist/features/blog/components/BlogIndexListing.js +21 -2
- package/dist/features/blog/components/BlogPostForm.js +11 -5
- package/dist/features/blog/components/BlogPostView.js +10 -2
- package/dist/features/blog/schemas/index.d.ts +18 -18
- package/dist/features/cart/components/CartDrawer.js +3 -2
- package/dist/features/cart/repository/cart.repository.js +4 -3
- package/dist/features/cart/utils/pending-ops.d.ts +1 -1
- package/dist/features/categories/api/[id]/route.js +4 -3
- package/dist/features/categories/api/route.js +4 -3
- package/dist/features/categories/components/BrandDetailPageView.js +2 -2
- package/dist/features/categories/components/BrandDetailTabs.js +2 -2
- package/dist/features/categories/components/BundleCollage.d.ts +8 -0
- package/dist/features/categories/components/BundleCollage.js +50 -0
- package/dist/features/categories/components/BundleDetailView.js +2 -10
- package/dist/features/categories/components/BundleItemsPicker.js +20 -13
- package/dist/features/categories/components/CategoriesIndexListing.js +28 -9
- package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
- package/dist/features/categories/components/CategoryDetailTabs.js +2 -2
- package/dist/features/categories/components/CategoryProductsListing.js +52 -13
- package/dist/features/categories/components/index.d.ts +2 -0
- package/dist/features/categories/components/index.js +1 -0
- package/dist/features/categories/schemas/index.d.ts +6 -6
- package/dist/features/checkout/actions/checkout-actions.js +4 -3
- package/dist/features/checkout/hooks/usePaymentCheckout.js +31 -22
- package/dist/features/classified/components/ClassifiedFilters.d.ts +8 -0
- package/dist/features/classified/components/ClassifiedFilters.js +19 -0
- package/dist/features/classified/components/ClassifiedIndexListing.d.ts +4 -0
- package/dist/features/classified/components/ClassifiedIndexListing.js +110 -0
- package/dist/features/classified/components/ClassifiedListView.d.ts +6 -0
- package/dist/features/classified/components/ClassifiedListView.js +43 -0
- package/dist/features/classified/components/index.d.ts +6 -0
- package/dist/features/classified/components/index.js +3 -0
- package/dist/features/collections/api/[slug]/route.js +16 -12
- package/dist/features/collections/schemas/index.d.ts +5 -5
- package/dist/features/consultation/api/[id]/route.js +12 -9
- package/dist/features/consultation/components/ConsultationForm.js +3 -2
- package/dist/features/consultation/schemas/index.d.ts +6 -6
- package/dist/features/contact/email.js +77 -116
- package/dist/features/copilot/components/AdminCopilotView.js +12 -2
- package/dist/features/corporate/api/[id]/route.js +12 -9
- package/dist/features/corporate/components/CorporateInquiryForm.js +2 -1
- package/dist/features/digital-codes/components/DigitalCodeFilters.d.ts +8 -0
- package/dist/features/digital-codes/components/DigitalCodeFilters.js +16 -0
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.d.ts +4 -0
- package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +107 -0
- package/dist/features/digital-codes/components/DigitalCodesListView.d.ts +6 -0
- package/dist/features/digital-codes/components/DigitalCodesListView.js +37 -0
- package/dist/features/digital-codes/components/index.d.ts +6 -0
- package/dist/features/digital-codes/components/index.js +3 -0
- package/dist/features/events/actions/event-actions.js +4 -3
- package/dist/features/events/components/AdminEventEditorView.js +3 -2
- package/dist/features/events/components/AdminEventsView.js +4 -2
- package/dist/features/events/components/EventPollWidget.js +5 -5
- package/dist/features/events/components/EventsIndexListing.js +2 -2
- package/dist/features/events/schemas/index.d.ts +20 -20
- package/dist/features/faq/actions/faq-actions.d.ts +8 -8
- package/dist/features/faq/components/ContactCTA.js +3 -1
- package/dist/features/faq/components/FAQAccordion.js +1 -1
- package/dist/features/faq/schemas/index.d.ts +4 -4
- package/dist/features/filters/AsyncFacetSection.d.ts +18 -0
- package/dist/features/filters/AsyncFacetSection.js +65 -0
- package/dist/features/forms/Checkbox.js +2 -2
- package/dist/features/forms/Input.js +2 -2
- package/dist/features/forms/Radio.js +5 -5
- package/dist/features/forms/Select.js +2 -2
- package/dist/features/forms/Slider.js +2 -2
- package/dist/features/forms/Textarea.js +2 -2
- package/dist/features/homepage/api/[id]/route.js +4 -3
- package/dist/features/homepage/api/sections/[id]/route.js +12 -9
- package/dist/features/homepage/components/AdSlot.js +2 -1
- package/dist/features/homepage/components/AdvertisementBanner.js +5 -3
- package/dist/features/homepage/components/BrandsSection.js +2 -2
- package/dist/features/homepage/components/CTABannerSection.js +2 -2
- package/dist/features/homepage/components/CharacterHotspot.d.ts +2 -2
- package/dist/features/homepage/components/CharacterHotspot.js +119 -157
- package/dist/features/homepage/components/CharacterHotspotForm.js +25 -20
- package/dist/features/homepage/components/CustomCardsSection.js +8 -6
- package/dist/features/homepage/components/FeaturedProductsSection.js +2 -2
- package/dist/features/homepage/components/GoogleReviewsSection.js +3 -3
- package/dist/features/homepage/components/HeroBanner.js +5 -4
- package/dist/features/homepage/components/HeroCarousel.js +13 -26
- package/dist/features/homepage/components/HowItWorksSection.js +4 -2
- package/dist/features/homepage/components/SocialFeedSection.js +2 -2
- package/dist/features/homepage/components/SocialPostCard.js +3 -2
- package/dist/features/homepage/lib/social-feed-fetcher.js +6 -3
- package/dist/features/layout/AppLayoutShell.d.ts +8 -2
- package/dist/features/layout/AppLayoutShell.js +55 -84
- package/dist/features/layout/BottomActions.js +43 -48
- package/dist/features/layout/NavbarWithSettings.d.ts +6 -0
- package/dist/features/layout/NavbarWithSettings.js +11 -0
- package/dist/features/live/components/LiveItemFilters.d.ts +8 -0
- package/dist/features/live/components/LiveItemFilters.js +23 -0
- package/dist/features/live/components/LiveItemsIndexListing.d.ts +4 -0
- package/dist/features/live/components/LiveItemsIndexListing.js +108 -0
- package/dist/features/live/components/LiveItemsListView.d.ts +6 -0
- package/dist/features/live/components/LiveItemsListView.js +43 -0
- package/dist/features/live/components/index.d.ts +6 -0
- package/dist/features/live/components/index.js +3 -0
- package/dist/features/media/MediaLightbox.js +8 -14
- package/dist/features/media/types/index.d.ts +2 -2
- package/dist/features/media/upload/CameraCapture.js +2 -2
- package/dist/features/media/upload/ImageUpload.js +4 -2
- package/dist/features/media/upload/MediaUploadField.js +24 -8
- package/dist/features/media/upload/MediaUploadList.js +1 -1
- package/dist/features/orders/actions/order-actions.js +4 -3
- package/dist/features/orders/components/MarketplaceOrderCard.js +2 -1
- package/dist/features/orders/components/OrderFilters.js +12 -9
- package/dist/features/orders/schemas/index.d.ts +6 -6
- package/dist/features/pre-orders/api/[id]/route.js +12 -9
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -4
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +27 -20
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +17 -52
- package/dist/features/pre-orders/components/PreorderCard.d.ts +0 -9
- package/dist/features/pre-orders/components/PreorderCard.js +2 -13
- package/dist/features/pre-orders/components/index.d.ts +1 -1
- package/dist/features/pre-orders/components/index.js +1 -1
- package/dist/features/pre-orders/schemas/index.d.ts +10 -10
- package/dist/features/products/api/[id]/route.js +9 -7
- package/dist/features/products/api/route.js +1 -1
- package/dist/features/products/columns/productTableColumns.js +2 -2
- package/dist/features/products/components/AuctionsIndexListing.js +15 -51
- package/dist/features/products/components/BidHistory.js +2 -2
- package/dist/features/products/components/CompareOverlay.js +3 -2
- package/dist/features/products/components/MakeOfferButton.js +20 -14
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +2 -1
- package/dist/features/products/components/PrizeDrawCollage.d.ts +1 -15
- package/dist/features/products/components/PrizeDrawCollage.js +54 -14
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -1
- package/dist/features/products/components/PrizeDrawEntryActions.js +2 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +9 -7
- package/dist/features/products/components/PrizeDrawsIndexListing.js +18 -51
- package/dist/features/products/components/PrizeRevealModal.js +24 -14
- package/dist/features/products/components/ProductDetailPageView.js +2 -1
- package/dist/features/products/components/ProductFilters.js +8 -6
- package/dist/features/products/components/ProductForm.js +12 -10
- package/dist/features/products/components/ProductGalleryClient.js +2 -1
- package/dist/features/products/components/ProductGrid.js +11 -14
- package/dist/features/products/components/ProductsIndexListing.js +16 -52
- package/dist/features/products/components/ProductsIndexPageView.js +2 -2
- package/dist/features/products/schemas/index.d.ts +56 -56
- package/dist/features/products/schemas/product-features.validators.d.ts +14 -14
- package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
- package/dist/features/promotions/schemas/index.d.ts +6 -6
- package/dist/features/reviews/actions/review-actions.js +6 -5
- package/dist/features/reviews/api/[id]/route.js +4 -3
- package/dist/features/reviews/components/ReviewDetailPageView.js +2 -2
- package/dist/features/reviews/components/ReviewDetailShell.js +6 -3
- package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
- package/dist/features/reviews/schemas/index.d.ts +6 -6
- package/dist/features/scams/components/ScamProfileView.js +19 -10
- package/dist/features/scams/components/ScamRegistryView.js +2 -1
- package/dist/features/search/components/Search.d.ts +1 -1
- package/dist/features/search/components/Search.js +56 -49
- package/dist/features/search/schemas/index.d.ts +5 -5
- package/dist/features/seller/actions/offer-actions.js +11 -9
- package/dist/features/seller/components/SellerAddressesView.js +6 -4
- package/dist/features/seller/components/SellerBidsView.js +2 -2
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerOffersPanel.js +6 -1
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +3 -3
- package/dist/features/seller/components/SellerPreOrdersView.js +5 -4
- package/dist/features/seller/components/SellerPrizeDrawsView.js +5 -4
- package/dist/features/seller/components/SellerProductShell.d.ts +19 -1
- package/dist/features/seller/components/SellerProductShell.js +75 -9
- package/dist/features/seller/components/SellerProductsView.js +10 -11
- package/dist/features/seller/components/SellerShippingView.js +3 -3
- package/dist/features/seller/components/SellerSidebar.js +10 -7
- package/dist/features/seller/components/SellerStorefrontView.js +3 -3
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/shell/FormShell.js +2 -1
- package/dist/features/shell/QuickFormDrawer.js +4 -3
- package/dist/features/shell/StepForm.js +4 -3
- package/dist/features/stores/actions/store-query-actions.js +4 -3
- package/dist/features/stores/components/StoreAboutView.js +2 -1
- package/dist/features/stores/components/StoreAuctionsListing.js +43 -64
- package/dist/features/stores/components/StoreDetailLayoutView.js +2 -2
- package/dist/features/stores/components/StorePreOrdersListing.js +33 -57
- package/dist/features/stores/components/StoreProductsListing.js +16 -49
- package/dist/features/stores/components/StoresIndexListing.js +2 -2
- package/dist/features/stores/schemas/index.d.ts +2 -2
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +8 -7
- package/dist/features/wishlist/hooks/useGuestWishlist.d.ts +5 -5
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +6 -6
- package/dist/features/wishlist/utils/guest-wishlist.d.ts +5 -5
- package/dist/index.d.ts +21 -3
- package/dist/index.js +1737 -1725
- package/dist/monitoring/server-logger.js +5 -9
- package/dist/next/api/apiHandler.js +56 -37
- package/dist/next/components/GlobalError.js +2 -1
- package/dist/next/routing/route-map.d.ts +27 -0
- package/dist/next/routing/route-map.js +10 -0
- package/dist/react/ErrorBoundary.js +2 -1
- package/dist/react/contexts/SessionContext.js +38 -28
- package/dist/react/hooks/useCamera.d.ts +1 -1
- package/dist/react/hooks/useCamera.js +8 -7
- package/dist/seed/site-settings-seed-data.js +6 -0
- package/dist/server-entry.d.ts +3 -0
- package/dist/server-entry.js +3 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.js +15 -0
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/DataTable.js +28 -7
- package/dist/ui/components/Button.d.ts +8 -1
- package/dist/ui/components/Button.js +47 -8
- package/dist/ui/components/CollageLightbox.d.ts +18 -0
- package/dist/ui/components/CollageLightbox.js +41 -0
- package/dist/ui/components/Dropdown.js +7 -6
- package/dist/ui/components/ImageLightbox.d.ts +7 -1
- package/dist/ui/components/ImageLightbox.js +15 -5
- package/dist/ui/components/PageLoader.js +4 -3
- package/dist/ui/components/PaginatedMultiSelect.d.ts +28 -0
- package/dist/ui/components/PaginatedMultiSelect.js +141 -0
- package/dist/ui/components/PaginatedMultiSelect.style.css +272 -0
- package/dist/ui/components/Semantic.js +1 -1
- package/dist/ui/components/SideDrawer.js +17 -15
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/utils/number.formatter.js +5 -13
- package/dist/utils/string.formatter.js +21 -18
- package/dist/validation/schemas.d.ts +2 -2
- package/package.json +2 -2
|
@@ -6,6 +6,11 @@ import { Button, Div, Heading, Input, Label, Li, Row, Span, Text, Textarea, Ul,
|
|
|
6
6
|
function randomId() {
|
|
7
7
|
return Math.random().toString(36).slice(2, 9);
|
|
8
8
|
}
|
|
9
|
+
const CLS_STEP = "space-y-4 rounded-lg border-2 p-6";
|
|
10
|
+
const CLS_IMG_WRAP = "relative w-full overflow-hidden rounded-lg";
|
|
11
|
+
const CLS_INPUT = "rounded border-2 px-3 py-2 text-sm outline-none";
|
|
12
|
+
const STY_BORDER_INK = "2px solid var(--border-ink)";
|
|
13
|
+
const STY_CENTERED = "translate(-50%, -50%)";
|
|
9
14
|
export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSave, }) {
|
|
10
15
|
const [imageUrl, setImageUrl] = useState(initial?.imageUrl ?? "");
|
|
11
16
|
const [imageAlt, setImageAlt] = useState(initial?.imageAlt ?? "DC, Marvel and Anime characters");
|
|
@@ -120,15 +125,15 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
|
|
|
120
125
|
: "var(--color-black)",
|
|
121
126
|
border: i <= stepIndex
|
|
122
127
|
? "2px solid var(--color-black)"
|
|
123
|
-
:
|
|
128
|
+
: STY_BORDER_INK,
|
|
124
129
|
}, children: i < stepIndex ? "✓" : i + 1 }), i < STEPS.length - 1 && (_jsx(Div, { className: "h-0.5 flex-1", style: {
|
|
125
130
|
background: i < stepIndex
|
|
126
131
|
? "var(--color-black)"
|
|
127
132
|
: "var(--border-ink)",
|
|
128
|
-
} }))] }), _jsx(Span, { className: "mt-1 text-center text-[10px] font-medium", style: { color: "var(--color-muted)" }, children: s.label })] }, s.key))) }), step === "image" && (_jsxs(Div, { className:
|
|
133
|
+
} }))] }), _jsx(Span, { className: "mt-1 text-center text-[10px] font-medium", style: { color: "var(--color-muted)" }, children: s.label })] }, s.key))) }), step === "image" && (_jsxs(Div, { className: CLS_STEP, style: {
|
|
129
134
|
borderColor: "var(--border-ink)",
|
|
130
135
|
background: "var(--surface-elevated)",
|
|
131
|
-
}, children: [_jsx(Heading, { level: 2, className: "text-lg font-bold", children: "Upload Background Image" }), _jsx(Text, { className: "text-sm", style: { color: "var(--color-muted)" }, children: "Choose a wide panoramic image that shows all the characters. You will place pins on it in the next step." }), _jsxs(Label, { className: "flex cursor-pointer flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed p-8 transition-colors hover:opacity-80", style: { borderColor: "var(--border-ink)" }, children: [_jsx(Span, { className: "text-3xl", children: "\uD83D\uDDBC" }), _jsx(Span, { className: "font-medium", children: uploading ? "Uploading…" : "Click to choose image" }), _jsx(Span, { className: "text-xs", style: { color: "var(--color-muted)" }, children: "JPG, PNG, WebP \u2014 wide landscape images work best" }), _jsx(Input, { type: "file", accept: "image/*", className: "hidden", onChange: handleImageUpload, disabled: uploading })] }), imageUrl && (_jsxs(Div, { className: "space-y-1", children: [_jsx(Div, { className:
|
|
136
|
+
}, children: [_jsx(Heading, { level: 2, className: "text-lg font-bold", children: "Upload Background Image" }), _jsx(Text, { className: "text-sm", style: { color: "var(--color-muted)" }, children: "Choose a wide panoramic image that shows all the characters. You will place pins on it in the next step." }), _jsxs(Label, { className: "flex cursor-pointer flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed p-8 transition-colors hover:opacity-80", style: { borderColor: "var(--border-ink)" }, children: [_jsx(Span, { className: "text-3xl", children: "\uD83D\uDDBC" }), _jsx(Span, { className: "font-medium", children: uploading ? "Uploading…" : "Click to choose image" }), _jsx(Span, { className: "text-xs", style: { color: "var(--color-muted)" }, children: "JPG, PNG, WebP \u2014 wide landscape images work best" }), _jsx(Input, { type: "file", accept: "image/*", className: "hidden", onChange: handleImageUpload, disabled: uploading })] }), imageUrl && (_jsxs(Div, { className: "space-y-1", children: [_jsx(Div, { className: CLS_IMG_WRAP, style: { paddingTop: "37.5%" }, children: _jsx(Image, { src: imageUrl, alt: imageAlt, fill: true, className: "object-cover", sizes: "680px" }) }), _jsx(Text, { className: "text-xs font-medium text-green-700", children: "\u2713 Image uploaded" })] })), _jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: "Image Alt Text" }), _jsx(Input, { type: "text", value: imageAlt, onChange: (e) => setImageAlt(e.target.value), placeholder: "DC, Marvel and Anime characters", className: CLS_INPUT, style: {
|
|
132
137
|
borderColor: "var(--border-ink)",
|
|
133
138
|
background: "var(--surface-elevated)",
|
|
134
139
|
color: "var(--color-black)",
|
|
@@ -138,17 +143,17 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
|
|
|
138
143
|
}, children: "Skip to Review" })), _jsx(Button, { type: "button", onClick: () => setStep("place"), disabled: !imageUrl || uploading, variant: "primary", className: "px-4 py-2 text-sm font-bold rounded transition-opacity disabled:opacity-50", style: {
|
|
139
144
|
background: "var(--color-black)",
|
|
140
145
|
color: "var(--color-yellow)",
|
|
141
|
-
}, children: "Next: Place Pins \u2192" })] })] })), step === "place" && (_jsxs(Div, { className:
|
|
146
|
+
}, children: "Next: Place Pins \u2192" })] })] })), step === "place" && (_jsxs(Div, { className: CLS_STEP, style: {
|
|
142
147
|
borderColor: "var(--border-ink)",
|
|
143
148
|
background: "var(--surface-elevated)",
|
|
144
|
-
}, children: [_jsx(Heading, { level: 2, className: "text-lg font-bold", children: "Place a Pin" }), _jsxs(Text, { className: "text-sm", style: { color: "var(--color-muted)" }, children: [_jsx("strong", { children: "Click anywhere on the image" }), " to drop a pin, or enter exact coordinates below."] }), _jsxs(Div, { ref: containerRef, className:
|
|
149
|
+
}, children: [_jsx(Heading, { level: 2, className: "text-lg font-bold", children: "Place a Pin" }), _jsxs(Text, { className: "text-sm", style: { color: "var(--color-muted)" }, children: [_jsx("strong", { children: "Click anywhere on the image" }), " to drop a pin, or enter exact coordinates below."] }), _jsxs(Div, { ref: containerRef, className: CLS_IMG_WRAP, style: {
|
|
145
150
|
paddingTop: "56.25%",
|
|
146
151
|
cursor: "crosshair",
|
|
147
152
|
background: "#111",
|
|
148
153
|
}, onClick: handleImageClick, children: [_jsx(Image, { src: imageUrl, alt: imageAlt, fill: true, className: "object-cover", sizes: "(max-width: 680px) 100vw" }), pins.map((pin) => (_jsxs(Div, { className: "pointer-events-none absolute", style: {
|
|
149
154
|
left: `${pin.xPct}%`,
|
|
150
155
|
top: `${pin.yPct}%`,
|
|
151
|
-
transform:
|
|
156
|
+
transform: STY_CENTERED,
|
|
152
157
|
zIndex: 10,
|
|
153
158
|
}, children: [_jsx(Div, { className: "flex items-center justify-center rounded-full text-xs font-bold text-white", style: {
|
|
154
159
|
width: 24,
|
|
@@ -159,7 +164,7 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
|
|
|
159
164
|
}, children: "+" }), pin.name && (_jsx(Div, { className: "pointer-events-none absolute left-7 top-1/2 -translate-y-1/2 whitespace-nowrap rounded px-1.5 py-0.5 text-[9px] font-bold text-white", style: { background: "#0D0D0D" }, children: pin.name }))] }, pin.id))), draftPos && (_jsxs(Div, { className: "absolute", style: {
|
|
160
165
|
left: `${draftPos.xPct}%`,
|
|
161
166
|
top: `${draftPos.yPct}%`,
|
|
162
|
-
transform:
|
|
167
|
+
transform: STY_CENTERED,
|
|
163
168
|
zIndex: 20,
|
|
164
169
|
}, children: [_jsx(Span, { className: "absolute animate-ping rounded-full", style: {
|
|
165
170
|
inset: -6,
|
|
@@ -201,18 +206,18 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
|
|
|
201
206
|
const v = parseFloat(e.target.value);
|
|
202
207
|
if (!isNaN(v))
|
|
203
208
|
onChange(v);
|
|
204
|
-
}, className:
|
|
209
|
+
}, className: CLS_INPUT, style: {
|
|
205
210
|
borderColor: "var(--border-ink)",
|
|
206
211
|
background: "var(--surface-elevated)",
|
|
207
212
|
color: "var(--color-black)",
|
|
208
213
|
} })] }, field))) }), pins.length > 0 && (_jsxs(Text, { className: "text-xs", style: { color: "var(--color-muted)" }, children: [pins.length, " pin", pins.length !== 1 ? "s" : "", " already placed on this image."] })), _jsxs(Row, { justify: "between", className: "border-t pt-4", style: { borderColor: "var(--border-ink)" }, children: [_jsx(Button, { type: "button", onClick: () => setStep("image"), variant: "ghost", className: "px-4 py-2 text-sm font-medium rounded transition-opacity hover:opacity-70", style: { background: "transparent", color: "var(--color-black)" }, children: "\u2190 Back" }), _jsxs(Row, { gap: "sm", children: [pins.length > 0 && (_jsx(Button, { type: "button", onClick: () => setStep("review"), variant: "outline", className: "px-4 py-2 text-sm font-bold rounded transition-opacity", style: {
|
|
209
214
|
background: "var(--surface-warm)",
|
|
210
215
|
color: "var(--color-black)",
|
|
211
|
-
border:
|
|
216
|
+
border: STY_BORDER_INK,
|
|
212
217
|
}, children: "Done Adding Pins" })), _jsx(Button, { type: "button", onClick: () => setStep("details"), disabled: !draftPos, variant: "primary", className: "px-4 py-2 text-sm font-bold rounded transition-opacity disabled:opacity-50", style: {
|
|
213
218
|
background: "var(--color-black)",
|
|
214
219
|
color: "var(--color-yellow)",
|
|
215
|
-
}, children: "Continue: Add Details \u2192" })] })] })] })), step === "details" && (_jsxs(Div, { className:
|
|
220
|
+
}, children: "Continue: Add Details \u2192" })] })] })] })), step === "details" && (_jsxs(Div, { className: CLS_STEP, style: {
|
|
216
221
|
borderColor: "var(--border-ink)",
|
|
217
222
|
background: "var(--surface-elevated)",
|
|
218
223
|
}, children: [_jsx(Heading, { level: 2, className: "text-lg font-bold", children: "Pin Details" }), _jsxs(Text, { className: "text-sm", style: { color: "var(--color-muted)" }, children: ["Fill in the details for the pin at", " ", _jsxs("strong", { children: [draftPos?.xPct, "%, ", draftPos?.yPct, "%"] }), "."] }), _jsx(Div, { className: "grid grid-cols-2 gap-3", children: [
|
|
@@ -228,7 +233,7 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
|
|
|
228
233
|
onChange: setDraftUniverse,
|
|
229
234
|
placeholder: "Marvel",
|
|
230
235
|
},
|
|
231
|
-
].map(({ label, value, onChange, placeholder }) => (_jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: label }), _jsx(Input, { type: "text", value: value, onChange: (e) => onChange(e.target.value), placeholder: placeholder, className:
|
|
236
|
+
].map(({ label, value, onChange, placeholder }) => (_jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: label }), _jsx(Input, { type: "text", value: value, onChange: (e) => onChange(e.target.value), placeholder: placeholder, className: CLS_INPUT, style: {
|
|
232
237
|
borderColor: "var(--border-ink)",
|
|
233
238
|
background: "var(--surface-elevated)",
|
|
234
239
|
color: "var(--color-black)",
|
|
@@ -236,7 +241,7 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
|
|
|
236
241
|
borderColor: "var(--border-ink)",
|
|
237
242
|
background: "var(--surface-elevated)",
|
|
238
243
|
color: "var(--color-black)",
|
|
239
|
-
}, placeholder: "Short description shown in the popup\u2026" })] }), _jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: "Link (href) *" }), _jsx(Input, { type: "text", value: draftHref, onChange: (e) => setDraftHref(e.target.value), placeholder: "/franchise/marvel", className:
|
|
244
|
+
}, placeholder: "Short description shown in the popup\u2026" })] }), _jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: "Link (href) *" }), _jsx(Input, { type: "text", value: draftHref, onChange: (e) => setDraftHref(e.target.value), placeholder: "/franchise/marvel", className: CLS_INPUT, style: {
|
|
240
245
|
borderColor: "var(--border-ink)",
|
|
241
246
|
background: "var(--surface-elevated)",
|
|
242
247
|
color: "var(--color-black)",
|
|
@@ -253,11 +258,11 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
|
|
|
253
258
|
onChange: setDraftBadge,
|
|
254
259
|
placeholder: "MARVEL",
|
|
255
260
|
},
|
|
256
|
-
].map(({ label, value, onChange, placeholder }) => (_jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: label }), _jsx(Input, { type: "text", value: value, onChange: (e) => onChange(e.target.value), placeholder: placeholder, className:
|
|
261
|
+
].map(({ label, value, onChange, placeholder }) => (_jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: label }), _jsx(Input, { type: "text", value: value, onChange: (e) => onChange(e.target.value), placeholder: placeholder, className: CLS_INPUT, style: {
|
|
257
262
|
borderColor: "var(--border-ink)",
|
|
258
263
|
background: "var(--surface-elevated)",
|
|
259
264
|
color: "var(--color-black)",
|
|
260
|
-
} })] }, label))) }), _jsxs(Row, { align: "end", gap: "sm", children: [_jsxs(Div, { className: "flex-1 flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: "Accent Colour (hex)" }), _jsx(Input, { type: "text", value: draftAccent, onChange: (e) => setDraftAccent(e.target.value), placeholder: "#E8001C", className:
|
|
265
|
+
} })] }, label))) }), _jsxs(Row, { align: "end", gap: "sm", children: [_jsxs(Div, { className: "flex-1 flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: "Accent Colour (hex)" }), _jsx(Input, { type: "text", value: draftAccent, onChange: (e) => setDraftAccent(e.target.value), placeholder: "#E8001C", className: CLS_INPUT, style: {
|
|
261
266
|
borderColor: "var(--border-ink)",
|
|
262
267
|
background: "var(--surface-elevated)",
|
|
263
268
|
color: "var(--color-black)",
|
|
@@ -267,20 +272,20 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
|
|
|
267
272
|
}, variant: "outline", className: "px-4 py-2 text-sm font-bold rounded transition-opacity disabled:opacity-50", style: {
|
|
268
273
|
background: "var(--surface-warm)",
|
|
269
274
|
color: "var(--color-black)",
|
|
270
|
-
border:
|
|
275
|
+
border: STY_BORDER_INK,
|
|
271
276
|
}, children: "Save Pin & Finish" }), _jsx(Button, { type: "button", disabled: !draftName || !draftHref, onClick: () => {
|
|
272
277
|
commitDraftPin();
|
|
273
278
|
setStep("place");
|
|
274
279
|
}, variant: "primary", className: "px-4 py-2 text-sm font-bold rounded transition-opacity disabled:opacity-50", style: {
|
|
275
280
|
background: "var(--color-black)",
|
|
276
281
|
color: "var(--color-yellow)",
|
|
277
|
-
}, children: "Save Pin & Add Another \u2192" })] })] })] })), step === "review" && (_jsxs(Div, { className:
|
|
282
|
+
}, children: "Save Pin & Add Another \u2192" })] })] })] })), step === "review" && (_jsxs(Div, { className: CLS_STEP, style: {
|
|
278
283
|
borderColor: "var(--border-ink)",
|
|
279
284
|
background: "var(--surface-elevated)",
|
|
280
|
-
}, children: [_jsxs(Row, { justify: "between", children: [_jsx(Heading, { level: 2, className: "text-lg font-bold", children: "Review & Save" }), _jsxs(Span, { className: "rounded-full px-3 py-1 text-sm font-bold", style: { background: "var(--surface-warm)" }, children: [pins.length, " pin", pins.length !== 1 ? "s" : ""] })] }), _jsxs(Div, { className:
|
|
285
|
+
}, children: [_jsxs(Row, { justify: "between", children: [_jsx(Heading, { level: 2, className: "text-lg font-bold", children: "Review & Save" }), _jsxs(Span, { className: "rounded-full px-3 py-1 text-sm font-bold", style: { background: "var(--surface-warm)" }, children: [pins.length, " pin", pins.length !== 1 ? "s" : ""] })] }), _jsxs(Div, { className: CLS_IMG_WRAP, style: { paddingTop: "56.25%", background: "#111" }, children: [_jsx(Image, { src: imageUrl, alt: imageAlt, fill: true, className: "object-cover", sizes: "(max-width: 680px) 100vw" }), pins.map((pin) => (_jsxs(Div, { className: "pointer-events-none absolute", style: {
|
|
281
286
|
left: `${pin.xPct}%`,
|
|
282
287
|
top: `${pin.yPct}%`,
|
|
283
|
-
transform:
|
|
288
|
+
transform: STY_CENTERED,
|
|
284
289
|
zIndex: 10,
|
|
285
290
|
}, children: [_jsx(Div, { className: "flex items-center justify-center rounded-full text-xs font-bold text-white", style: {
|
|
286
291
|
width: 28,
|
|
@@ -291,7 +296,7 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
|
|
|
291
296
|
}, children: "+" }), pin.name && (_jsx(Div, { className: "pointer-events-none absolute left-8 top-1/2 -translate-y-1/2 whitespace-nowrap rounded px-1.5 py-0.5 text-[9px] font-bold text-white", style: { background: "#0D0D0D" }, children: pin.name }))] }, pin.id)))] }), pins.length > 0 ? (_jsx(Ul, { className: "divide-y rounded-lg border", style: { borderColor: "var(--border-ink)" }, children: pins.map((pin, i) => (_jsx(Li, { className: "px-4 py-3", children: _jsxs(Row, { gap: "sm", children: [_jsx(Span, { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-xs font-bold text-white", style: { background: pin.accent || "#E8001C" }, children: i + 1 }), _jsxs(Div, { className: "min-w-0 flex-1", children: [_jsx(Text, { className: "truncate text-sm font-bold", children: pin.name || (_jsx(Span, { className: "italic", style: { color: "var(--color-muted)" }, children: "Unnamed" })) }), _jsxs(Text, { className: "text-xs", style: { color: "var(--color-muted)" }, children: [pin.universe, " \u00B7 ", pin.xPct.toFixed(0), "%,", " ", pin.yPct.toFixed(0), "%"] })] }), _jsx(Button, { type: "button", onClick: () => deletePin(pin.id), variant: "ghost", className: "shrink-0 rounded p-1 text-xs text-red-500 hover:bg-red-50", title: "Remove pin", children: "\u2715" })] }) }, pin.id))) })) : (_jsx(Div, { className: "rounded-lg border-2 border-dashed p-8 text-center text-sm", style: {
|
|
292
297
|
borderColor: "var(--border-ink)",
|
|
293
298
|
color: "var(--color-muted)",
|
|
294
|
-
}, children: "No pins yet \u2014 add some using the button below." })), _jsxs("details", { className: "rounded-lg border p-3", style: { borderColor: "var(--border-ink)" }, children: [_jsx("summary", { className: "cursor-pointer text-sm font-medium", children: "Image Settings" }), _jsxs(Div, { className: "mt-3 space-y-3", children: [_jsxs(Label, { className: "inline-flex cursor-pointer items-center gap-2 rounded border-2 border-dashed px-3 py-1.5 text-sm font-medium transition-colors hover:opacity-80", style: { borderColor: "var(--border-ink)" }, children: [uploading ? "Uploading…" : "Replace Image", _jsx(Input, { type: "file", accept: "image/*", className: "hidden", onChange: handleImageUpload, disabled: uploading })] }), _jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: "Image Alt Text" }), _jsx(Input, { type: "text", value: imageAlt, onChange: (e) => setImageAlt(e.target.value), className:
|
|
299
|
+
}, children: "No pins yet \u2014 add some using the button below." })), _jsxs("details", { className: "rounded-lg border p-3", style: { borderColor: "var(--border-ink)" }, children: [_jsx("summary", { className: "cursor-pointer text-sm font-medium", children: "Image Settings" }), _jsxs(Div, { className: "mt-3 space-y-3", children: [_jsxs(Label, { className: "inline-flex cursor-pointer items-center gap-2 rounded border-2 border-dashed px-3 py-1.5 text-sm font-medium transition-colors hover:opacity-80", style: { borderColor: "var(--border-ink)" }, children: [uploading ? "Uploading…" : "Replace Image", _jsx(Input, { type: "file", accept: "image/*", className: "hidden", onChange: handleImageUpload, disabled: uploading })] }), _jsxs(Div, { className: "flex flex-col gap-1", children: [_jsx(Label, { className: "text-sm font-bold", children: "Image Alt Text" }), _jsx(Input, { type: "text", value: imageAlt, onChange: (e) => setImageAlt(e.target.value), className: CLS_INPUT, style: {
|
|
295
300
|
borderColor: "var(--border-ink)",
|
|
296
301
|
background: "var(--surface-elevated)",
|
|
297
302
|
color: "var(--color-black)",
|
|
@@ -301,7 +306,7 @@ export function CharacterHotspotForm({ initial, onUploadImage, onSave, onAfterSa
|
|
|
301
306
|
}, variant: "outline", className: "px-4 py-2 text-sm font-bold rounded transition-opacity", style: {
|
|
302
307
|
background: "var(--surface-warm)",
|
|
303
308
|
color: "var(--color-black)",
|
|
304
|
-
border:
|
|
309
|
+
border: STY_BORDER_INK,
|
|
305
310
|
}, children: "+ Add Another Pin" }), _jsx(Button, { type: "button", onClick: handleSave, disabled: !imageUrl || saving || pins.length === 0, variant: "primary", className: "px-4 py-2 text-sm font-bold rounded transition-opacity disabled:opacity-50", style: {
|
|
306
311
|
background: "var(--color-black)",
|
|
307
312
|
color: "var(--color-yellow)",
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Heading, HorizontalScroller, Section } from "../../../ui";
|
|
2
|
+
import { Heading, HorizontalScroller, Section, Text } from "../../../ui";
|
|
3
3
|
import { THEME_CONSTANTS } from "../../../tokens";
|
|
4
4
|
import { SectionCarousel } from "./SectionCarousel";
|
|
5
5
|
import { MediaImage } from "../../media/MediaImage";
|
|
6
|
+
// --- Constants ---------------------------------------------------------------
|
|
7
|
+
const CLS_CONTAINER = "w-full max-w-7xl mx-auto px-4";
|
|
6
8
|
// --- Helpers -----------------------------------------------------------------
|
|
7
9
|
const COLS_CLASS = {
|
|
8
10
|
1: "grid-cols-1",
|
|
@@ -39,7 +41,7 @@ function CardItem({ card }) {
|
|
|
39
41
|
cardStyle.backgroundColor = card.backgroundColor;
|
|
40
42
|
if (card.textColor)
|
|
41
43
|
cardStyle.color = card.textColor;
|
|
42
|
-
return (_jsxs("div", { className: `flex flex-col overflow-hidden ${radiusClass} ${shadowClass} bg-[var(--appkit-color-surface)]`, style: cardStyle, children: [card.image && (_jsx("div", { className: "relative w-full aspect-video overflow-hidden", children: _jsx(MediaImage, { src: card.image, alt: card.imageAlt ?? "", size: "card" }) })), _jsxs("div", { className: "flex flex-col gap-2 p-4 flex-1", children: [card.eyebrow && (_jsx(
|
|
44
|
+
return (_jsxs("div", { className: `flex flex-col overflow-hidden ${radiusClass} ${shadowClass} bg-[var(--appkit-color-surface)]`, style: cardStyle, children: [card.image && (_jsx("div", { className: "relative w-full aspect-video overflow-hidden", children: _jsx(MediaImage, { src: card.image, alt: card.imageAlt ?? "", size: "card" }) })), _jsxs("div", { className: "flex flex-col gap-2 p-4 flex-1", children: [card.eyebrow && (_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest opacity-70", children: card.eyebrow })), card.title && (_jsx(Text, { className: "text-base font-bold leading-snug", children: card.title })), card.body && (_jsx(Text, { className: "text-sm opacity-80 leading-relaxed flex-1", children: card.body })), card.buttons && card.buttons.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-2 mt-2", children: card.buttons.map((btn, i) => (_jsx("a", { href: btn.href, target: btn.target ?? "_self", rel: btn.target === "_blank" ? "noopener noreferrer" : undefined, className: VARIANT_CLASS[btn.variant] ?? VARIANT_CLASS.primary, children: btn.label }, i))) })), card.formEmbed && (_jsx("iframe", { src: card.formEmbed, sandbox: "allow-forms allow-scripts", loading: "lazy", className: "w-full mt-3 border-0 rounded-md", style: { minHeight: "200px" }, title: "Embedded form" }))] })] }));
|
|
43
45
|
}
|
|
44
46
|
// --- Section Header ----------------------------------------------------------
|
|
45
47
|
function SectionHeader({ title }) {
|
|
@@ -55,11 +57,11 @@ export function CustomCardsSection(config) {
|
|
|
55
57
|
return null;
|
|
56
58
|
// autoScroll: wrap all cards in SectionCarousel (client carousel)
|
|
57
59
|
if (autoScroll) {
|
|
58
|
-
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsx("div", { className:
|
|
60
|
+
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsx("div", { className: CLS_CONTAINER, children: _jsx(SectionCarousel, { title: title ?? "", items: cards, renderItem: (card) => _jsx(CardItem, { card: card }), keyExtractor: (card) => card.id, autoScroll: true, autoScrollInterval: scrollIntervalMs ?? 3500, perView: { base: 1, sm: 2, md: columns } }) }) }));
|
|
59
61
|
}
|
|
60
62
|
// Row layout: horizontal scroller
|
|
61
63
|
if (layout === "row") {
|
|
62
|
-
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsxs("div", { className:
|
|
64
|
+
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsxs("div", { className: CLS_CONTAINER, children: [_jsx(SectionHeader, { title: title }), _jsx(HorizontalScroller, { gap: 16, showArrows: true, snapToItems: true, children: cards.map((card) => (_jsx("div", { className: "w-72 flex-shrink-0", children: _jsx(CardItem, { card: card }) }, card.id))) })] }) }));
|
|
63
65
|
}
|
|
64
66
|
// Masonry layout: CSS columns
|
|
65
67
|
if (layout === "masonry") {
|
|
@@ -68,9 +70,9 @@ export function CustomCardsSection(config) {
|
|
|
68
70
|
.split(" ")
|
|
69
71
|
.map((c) => c.replace("grid-cols-", "columns-"))
|
|
70
72
|
.join(" ");
|
|
71
|
-
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsxs("div", { className:
|
|
73
|
+
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsxs("div", { className: CLS_CONTAINER, children: [_jsx(SectionHeader, { title: title }), _jsx("div", { className: `${masonryClass} gap-4 space-y-4`, children: cards.map((card) => (_jsx("div", { className: "break-inside-avoid", children: _jsx(CardItem, { card: card }) }, card.id))) })] }) }));
|
|
72
74
|
}
|
|
73
75
|
// Grid layout (default)
|
|
74
76
|
const colsClass = COLS_CLASS[columns] ?? COLS_CLASS[3];
|
|
75
|
-
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsxs("div", { className:
|
|
77
|
+
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsxs("div", { className: CLS_CONTAINER, children: [_jsx(SectionHeader, { title: title }), _jsx("div", { className: `grid ${colsClass} gap-4`, children: cards.map((card) => (_jsx(CardItem, { card: card }, card.id))) })] }) }));
|
|
76
78
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect, useRef } from "react";
|
|
4
4
|
import Link from "next/link";
|
|
5
5
|
import { SectionCarousel } from "./SectionCarousel";
|
|
@@ -32,7 +32,7 @@ function ProductGrid({ items, rows, maxItems, pagination, viewMoreHref, viewMore
|
|
|
32
32
|
return () => { if (timerRef.current)
|
|
33
33
|
clearInterval(timerRef.current); };
|
|
34
34
|
}, [pagination, pageSize, totalItems]);
|
|
35
|
-
return (_jsx(Section, { className: `py-12 px-4 ${themed.bgPrimary}`, children: _jsxs("div", { className: "mx-auto max-w-7xl", children: [_jsxs("div", { className: "mb-6 flex items-end justify-between gap-4", children: [_jsxs(
|
|
35
|
+
return (_jsx(Section, { className: `py-12 px-4 ${themed.bgPrimary}`, children: _jsxs("div", { className: "mx-auto max-w-7xl", children: [_jsxs("div", { className: "mb-6 flex items-end justify-between gap-4", children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 2, className: `text-2xl font-bold md:text-3xl ${themed.textPrimary}`, children: title }), description && (_jsx(Text, { variant: "muted", className: "mt-1 text-sm", children: description }))] }), pagination === "arrows" && (_jsxs("div", { className: "flex shrink-0 gap-2", children: [_jsx("button", { type: "button", onClick: prev, disabled: !canPrev, "aria-label": "Previous", className: "flex h-9 w-9 items-center justify-center rounded-full border border-zinc-200 bg-white text-zinc-600 hover:border-[var(--appkit-color-primary)] hover:text-[var(--appkit-color-primary)] disabled:opacity-40 dark:border-slate-700 dark:bg-slate-900 dark:text-zinc-300", children: "\u2039" }), _jsx("button", { type: "button", onClick: next, disabled: !canNext, "aria-label": "Next", className: "flex h-9 w-9 items-center justify-center rounded-full border border-zinc-200 bg-white text-zinc-600 hover:border-[var(--appkit-color-primary)] hover:text-[var(--appkit-color-primary)] disabled:opacity-40 dark:border-slate-700 dark:bg-slate-900 dark:text-zinc-300", children: "\u203A" })] }))] }), _jsx("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5", children: visible.map((product) => (_jsx(InteractiveProductCard, { product: product, href: String(ROUTES.PUBLIC.PRODUCT_DETAIL(product.slug ?? product.id ?? "")) }, product.id))) }), pagination === "load-more" && canNext && (_jsx("div", { className: "mt-8 text-center", children: _jsx("button", { type: "button", onClick: next, className: "rounded-lg border border-zinc-300 bg-white px-6 py-2 text-sm font-medium text-zinc-700 hover:border-[var(--appkit-color-primary)] hover:text-[var(--appkit-color-primary)] dark:border-slate-600 dark:bg-slate-900 dark:text-zinc-300", children: "Load more" }) })), viewMoreHref && (_jsx("div", { className: "mt-6 text-center", children: _jsx(Link, { href: viewMoreHref, className: "text-sm font-medium text-[var(--appkit-color-primary)] hover:opacity-80", children: viewMoreLabel }) }))] }) }));
|
|
36
36
|
}
|
|
37
37
|
// --- Main component -----------------------------------------------------------
|
|
38
38
|
export function FeaturedProductsSection({ title = "Featured Products", description, viewMoreHref, viewMoreLabel = "View all products →", className = "", filterByBrand, initialItems, rows = 1, maxItems, pagination = "load-more", }) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Heading, Section, Text } from "../../../ui";
|
|
3
3
|
import { THEME_CONSTANTS } from "../../../tokens";
|
|
4
4
|
import { siteSettingsRepository } from "../../admin/repository/site-settings.repository";
|
|
@@ -20,7 +20,7 @@ function ReviewCard({ review, showRating, showDate, }) {
|
|
|
20
20
|
day: "numeric",
|
|
21
21
|
})
|
|
22
22
|
: null;
|
|
23
|
-
return (_jsxs("div", { className: "flex flex-col gap-3 p-4 rounded-xl bg-[var(--appkit-color-surface)] shadow-sm border border-[var(--appkit-color-border)]", children: [_jsxs("div", { className: "flex items-center gap-3", children: [review.authorPhotoUrl ? (_jsx("img", { src: review.authorPhotoUrl, alt: review.authorName, className: "w-9 h-9 rounded-full object-cover flex-shrink-0", loading: "lazy", referrerPolicy: "no-referrer" })) : (_jsx("div", { className: "w-9 h-9 rounded-full bg-[var(--appkit-color-primary)] flex items-center justify-center flex-shrink-0", children: _jsx("span", { className: "text-white text-sm font-bold", children: review.authorName.charAt(0).toUpperCase() }) })), _jsxs("div", { className: "min-w-0", children: [_jsx(
|
|
23
|
+
return (_jsxs("div", { className: "flex flex-col gap-3 p-4 rounded-xl bg-[var(--appkit-color-surface)] shadow-sm border border-[var(--appkit-color-border)]", children: [_jsxs("div", { className: "flex items-center gap-3", children: [review.authorPhotoUrl ? (_jsx("img", { src: review.authorPhotoUrl, alt: review.authorName, className: "w-9 h-9 rounded-full object-cover flex-shrink-0", loading: "lazy", referrerPolicy: "no-referrer" })) : (_jsx("div", { className: "w-9 h-9 rounded-full bg-[var(--appkit-color-primary)] flex items-center justify-center flex-shrink-0", children: _jsx("span", { className: "text-white text-sm font-bold", children: review.authorName.charAt(0).toUpperCase() }) })), _jsxs("div", { className: "min-w-0", children: [_jsx(Text, { className: "text-sm font-semibold truncate", children: review.authorName }), dateStr && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: dateStr }))] })] }), showRating && _jsx(StarRating, { rating: review.rating }), review.text && (_jsx(Text, { className: "text-sm leading-relaxed text-zinc-700 dark:text-zinc-300 line-clamp-4", children: review.text })), _jsx(GoogleBadge, {})] }));
|
|
24
24
|
}
|
|
25
25
|
// --- Empty / Not Configured States -------------------------------------------
|
|
26
26
|
function NotConfiguredState() {
|
|
@@ -61,5 +61,5 @@ export async function GoogleReviewsSection(config) {
|
|
|
61
61
|
: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4";
|
|
62
62
|
const cardClass = layout === "carousel" ? "flex-shrink-0 w-72 snap-start" : "";
|
|
63
63
|
const mapsHref = googleMapsUrl || (placeId ? `https://search.google.com/local/reviews?placeid=${placeId}` : "");
|
|
64
|
-
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsxs("div", { className: "w-full max-w-7xl mx-auto px-4", children: [_jsxs("div", { className: "mb-8 flex items-end justify-between gap-4", children: [_jsxs(
|
|
64
|
+
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsxs("div", { className: "w-full max-w-7xl mx-auto px-4", children: [_jsxs("div", { className: "mb-8 flex items-end justify-between gap-4", children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 2, children: "What Our Customers Say" }), aggregateRating > 0 && (_jsxs("div", { className: "flex items-center gap-2 mt-1", children: [_jsx(StarRating, { rating: Math.round(aggregateRating) }), _jsxs(Text, { size: "sm", variant: "muted", children: [aggregateRating.toFixed(1), " \u00B7 ", totalRatings.toLocaleString(), " reviews"] })] }))] }), linkToGoogleMaps && mapsHref && (_jsx("a", { href: mapsHref, target: "_blank", rel: "noopener noreferrer", className: "shrink-0 text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline", children: "View on Google \u2192" }))] }), reviews.length === 0 ? (_jsx(EmptyState, {})) : (_jsx("div", { className: gridClass, children: reviews.map((review, i) => (_jsx("div", { className: cardClass, children: _jsx(ReviewCard, { review: review, showRating: showRating, showDate: showDate }) }, `${review.authorName}-${i}`))) }))] }) }));
|
|
65
65
|
}
|
|
@@ -4,6 +4,7 @@ import { useState, useEffect, useCallback } from "react";
|
|
|
4
4
|
import Image from "next/image";
|
|
5
5
|
import Link from "next/link";
|
|
6
6
|
import { Button, Div, Heading, Row, Span } from "../../../ui";
|
|
7
|
+
const FONT_BANGERS = "var(--font-bangers, Bangers, cursive)";
|
|
7
8
|
export function HeroBanner({ banners, autoplayMs = 5000 }) {
|
|
8
9
|
const [current, setCurrent] = useState(0);
|
|
9
10
|
const [animating, setAnimating] = useState(false);
|
|
@@ -45,16 +46,16 @@ export function HeroBanner({ banners, autoplayMs = 5000 }) {
|
|
|
45
46
|
}, children: [banner.subtitle && (_jsx(Div, { className: "mb-3", children: _jsx(Span, { className: "inline-block px-3 py-1 text-xs font-black uppercase tracking-[0.18em]", style: {
|
|
46
47
|
background: "var(--color-red)",
|
|
47
48
|
color: "#FFFFFF",
|
|
48
|
-
fontFamily:
|
|
49
|
+
fontFamily: FONT_BANGERS,
|
|
49
50
|
letterSpacing: "0.16em",
|
|
50
51
|
}, children: banner.subtitle }) })), _jsx(Heading, { level: 2, className: "mb-5 max-w-xl leading-none", style: {
|
|
51
|
-
fontFamily:
|
|
52
|
+
fontFamily: FONT_BANGERS,
|
|
52
53
|
fontSize: "clamp(3rem, 9vw, 6.5rem)",
|
|
53
54
|
letterSpacing: "0.04em",
|
|
54
55
|
color: banner.textColor ?? "#FFFFFF",
|
|
55
56
|
textShadow: "0 4px 32px rgba(0,0,0,0.5)",
|
|
56
57
|
}, children: banner.title }), banner.ctaLabel && banner.ctaUrl && (_jsx(Row, { wrap: true, gap: "md", children: _jsxs(Link, { href: banner.ctaUrl, className: "inline-flex items-center gap-2 sm:gap-3 px-5 py-3 sm:px-8 sm:py-3.5 font-black uppercase transition-all hover:-translate-y-0.5", style: {
|
|
57
|
-
fontFamily:
|
|
58
|
+
fontFamily: FONT_BANGERS,
|
|
58
59
|
letterSpacing: "0.1em",
|
|
59
60
|
fontSize: "clamp(0.85rem, 2.5vw, 1.1rem)",
|
|
60
61
|
background: "var(--color-yellow)",
|
|
@@ -78,7 +79,7 @@ export function HeroBanner({ banners, autoplayMs = 5000 }) {
|
|
|
78
79
|
backdropFilter: "blur(6px)",
|
|
79
80
|
}, children: _jsx("svg", { className: "h-4 w-4 sm:h-5 sm:w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M9 5l7 7-7 7" }) }) })] })), banners.length > 1 && (_jsxs(Row, { className: "absolute bottom-8 right-6 sm:right-12 gap-3", style: { zIndex: 15 }, children: [_jsxs(Span, { className: "text-xs font-black tabular-nums", style: {
|
|
80
81
|
color: "rgba(255,255,255,0.6)",
|
|
81
|
-
fontFamily:
|
|
82
|
+
fontFamily: FONT_BANGERS,
|
|
82
83
|
letterSpacing: "0.1em",
|
|
83
84
|
}, children: [String(current + 1).padStart(2, "0"), " /", " ", String(banners.length).padStart(2, "0")] }), _jsx(Div, { className: "flex gap-1.5", children: banners.map((_, i) => (_jsx(Button, { onClick: () => goTo(i), "aria-label": `Go to slide ${i + 1}`, variant: "ghost", size: "sm", className: "transition-all", style: {
|
|
84
85
|
height: 3,
|
|
@@ -8,6 +8,16 @@ import { MediaImage } from "../../media/MediaImage";
|
|
|
8
8
|
import { MediaVideo } from "../../media/MediaVideo";
|
|
9
9
|
import { useHeroCarousel } from "../hooks/useHeroCarousel";
|
|
10
10
|
const { flex, position } = THEME_CONSTANTS;
|
|
11
|
+
function makeButtonClickHandler(href, openInNewTab, push) {
|
|
12
|
+
return () => {
|
|
13
|
+
if (openInNewTab) {
|
|
14
|
+
window.open(href, "_blank", "noopener,noreferrer");
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
navigate(href, push);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
11
21
|
function navigate(href, push) {
|
|
12
22
|
if (push) {
|
|
13
23
|
push(href);
|
|
@@ -94,23 +104,8 @@ function CarouselCardRenderer({ card, isMobile, push, }) {
|
|
|
94
104
|
const variant = btn.variant === "link" || btn.variant === "ghost"
|
|
95
105
|
? "ghost"
|
|
96
106
|
: btn.variant;
|
|
97
|
-
return (_jsx(Button, { variant: variant, size: "sm", onClick: ()
|
|
98
|
-
|
|
99
|
-
window.open(btn.href, "_blank", "noopener,noreferrer");
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
navigate(btn.href, push);
|
|
103
|
-
}
|
|
104
|
-
}, children: btn.text }, btn.id ?? i));
|
|
105
|
-
}) }))] })), card.isButtonOnly && card.buttons?.[0] && (_jsx(Button, { variant: "ghost", className: `${position.fill} ${flex.center} font-semibold text-white hover:bg-black/20 transition-colors rounded-none p-0`, onClick: () => {
|
|
106
|
-
const btn = card.buttons[0];
|
|
107
|
-
if (btn.openInNewTab) {
|
|
108
|
-
window.open(btn.href, "_blank", "noopener,noreferrer");
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
navigate(btn.href, push);
|
|
112
|
-
}
|
|
113
|
-
}, children: _jsx(Span, { className: "text-lg md:text-2xl", children: card.buttons[0].text }) }))] }));
|
|
107
|
+
return (_jsx(Button, { variant: variant, size: "sm", onClick: makeButtonClickHandler(btn.href, btn.openInNewTab, push), children: btn.text }, btn.id ?? i));
|
|
108
|
+
}) }))] })), card.isButtonOnly && card.buttons?.[0] && (_jsx(Button, { variant: "ghost", className: `${position.fill} ${flex.center} font-semibold text-white hover:bg-black/20 transition-colors rounded-none p-0`, onClick: makeButtonClickHandler(card.buttons[0].href, card.buttons[0].openInNewTab, push), children: _jsx(Span, { className: "text-lg md:text-2xl", children: card.buttons[0].text }) }))] }));
|
|
114
109
|
}
|
|
115
110
|
export function HeroCarousel({ initialSlides, push } = {}) {
|
|
116
111
|
const [currentSlide, setCurrentSlide] = useState(0);
|
|
@@ -174,15 +169,7 @@ export function HeroCarousel({ initialSlides, push } = {}) {
|
|
|
174
169
|
return (_jsxs(Section, { ref: sectionRef, className: `relative w-full ${heightClass} overflow-hidden`, "aria-roledescription": "carousel", "aria-label": "Hero carousel", onKeyDown: handleKeyDown, onMouseEnter: () => setIsPaused(true), onMouseLeave: () => setIsPaused(false), onFocus: () => setIsPaused(true), onBlur: () => setIsPaused(false), tabIndex: 0, children: [_jsx(Div, { "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: `Slide ${currentSlide + 1} of ${slides.length}` }), _jsx(Div, { className: position.fill, children: _jsx(Div, { ref: slidesRef, onScroll: handleSlidesScroll, className: "flex h-full overflow-x-auto scroll-smooth snap-x snap-mandatory [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", style: { gap: 0 }, children: slides.map((slide, slideIndex) => {
|
|
175
170
|
const slideHeightClass = getSlideHeightClass(slide.settings?.height);
|
|
176
171
|
const hasCards = slide.cards && slide.cards.length > 0;
|
|
177
|
-
return (_jsxs(Div, { className: `snap-start flex-none w-full relative self-stretch bg-zinc-900 ${slideHeightClass}`, children: [_jsx(Div, { className: position.fill, children: _jsx(SlideBackground, { bg: slide.background, legacy: slide.media, mobileLegacy: slide.mobileMedia, isMobile: isMobile, priority: slideIndex === 0 }) }), slide.overlay && (_jsxs(Div, { className: `${position.fill} ${flex.center} flex-col text-center px-6 md:px-16 lg:px-32`, children: [slide.overlay.subtitle && (_jsx(Text, { className: "stagger-1 text-xs md:text-sm !text-white/80 mb-1 md:mb-2 drop-shadow-sm uppercase tracking-widest", children: slide.overlay.subtitle })), slide.overlay.title && (_jsx(Heading, { level: 1, className: "stagger-2 font-display text-4xl md:text-6xl lg:text-8xl !text-white drop-shadow-2xl mb-2 md:mb-4", children: slide.overlay.title })), slide.overlay.description && (_jsx(Text, { className: "stagger-3 text-sm md:text-lg lg:text-xl !text-white/90 mb-4 md:mb-8 drop-shadow-sm max-w-2xl mx-auto", children: slide.overlay.description })), slide.overlay.button && (_jsx(Div, { className: "stagger-4", children: _jsx(Button, { variant: slide.overlay.button.variant, size: "sm", onClick: ()
|
|
178
|
-
const btn = slide.overlay.button;
|
|
179
|
-
if (btn.openInNewTab) {
|
|
180
|
-
window.open(btn.link, "_blank", "noopener,noreferrer");
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
navigate(btn.link, push);
|
|
184
|
-
}
|
|
185
|
-
}, children: slide.overlay.button.text }) }))] })), hasCards && (_jsx(Div, { className: `${position.fill} grid gap-2 md:gap-4 p-4 md:p-8`, style: {
|
|
172
|
+
return (_jsxs(Div, { className: `snap-start flex-none w-full relative self-stretch bg-zinc-900 ${slideHeightClass}`, children: [_jsx(Div, { className: position.fill, children: _jsx(SlideBackground, { bg: slide.background, legacy: slide.media, mobileLegacy: slide.mobileMedia, isMobile: isMobile, priority: slideIndex === 0 }) }), slide.overlay && (_jsxs(Div, { className: `${position.fill} ${flex.center} flex-col text-center px-6 md:px-16 lg:px-32`, children: [slide.overlay.subtitle && (_jsx(Text, { className: "stagger-1 text-xs md:text-sm !text-white/80 mb-1 md:mb-2 drop-shadow-sm uppercase tracking-widest", children: slide.overlay.subtitle })), slide.overlay.title && (_jsx(Heading, { level: 1, className: "stagger-2 font-display text-4xl md:text-6xl lg:text-8xl !text-white drop-shadow-2xl mb-2 md:mb-4", children: slide.overlay.title })), slide.overlay.description && (_jsx(Text, { className: "stagger-3 text-sm md:text-lg lg:text-xl !text-white/90 mb-4 md:mb-8 drop-shadow-sm max-w-2xl mx-auto", children: slide.overlay.description })), slide.overlay.button && (_jsx(Div, { className: "stagger-4", children: _jsx(Button, { variant: slide.overlay.button.variant, size: "sm", onClick: makeButtonClickHandler(slide.overlay.button.link, slide.overlay.button.openInNewTab, push), children: slide.overlay.button.text }) }))] })), hasCards && (_jsx(Div, { className: `${position.fill} grid gap-2 md:gap-4 p-4 md:p-8`, style: {
|
|
186
173
|
gridTemplateRows: "repeat(2, 1fr)",
|
|
187
174
|
gridTemplateColumns: isMobile ? "1fr" : "repeat(3, 1fr)",
|
|
188
175
|
alignContent: "center",
|
|
@@ -3,6 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useEffect, useRef, useState } from "react";
|
|
4
4
|
import { THEME_CONSTANTS } from "../../../tokens";
|
|
5
5
|
import { Button, Div, Grid, Heading, Section, Text } from "../../../ui";
|
|
6
|
+
// --- Constants ---------------------------------------------------------------
|
|
7
|
+
const CLS_VISIBLE = "opacity-100 translate-y-0";
|
|
6
8
|
// --- Single step card ---------------------------------------------------------
|
|
7
9
|
function StepCard({ step, visible, delay, }) {
|
|
8
10
|
const { badgeBg = "bg-primary", iconColor = "text-primary", iconBg = "bg-primary/5 dark:bg-primary/10", } = step;
|
|
@@ -11,7 +13,7 @@ function StepCard({ step, visible, delay, }) {
|
|
|
11
13
|
"bg-white dark:bg-slate-900",
|
|
12
14
|
"shadow-md group hover:-translate-y-2 hover:shadow-xl",
|
|
13
15
|
"transition-all duration-300",
|
|
14
|
-
visible ?
|
|
16
|
+
visible ? CLS_VISIBLE : "opacity-0 translate-y-8",
|
|
15
17
|
].join(" "), style: { transitionDelay: `${delay}ms` }, "data-section": "howitworkssection-div-340", children: [_jsx("div", { className: "absolute top-4 right-5 font-display text-7xl bg-gradient-to-br from-primary to-cobalt opacity-10 bg-clip-text text-transparent select-none pointer-events-none leading-none", "aria-hidden": "true", "data-section": "howitworkssection-div-341", children: step.number }), _jsx("div", { className: `relative z-10 w-10 h-10 rounded-full ${badgeBg} text-white font-bold text-sm flex items-center justify-center mb-5 shadow-md`, "data-section": "howitworkssection-div-342", children: step.number }), step.renderIcon && (_jsx("div", { className: `relative z-10 w-14 h-14 rounded-2xl ${iconBg} flex items-center justify-center mb-4 border border-white/80 dark:border-slate-700/50`, "data-section": "howitworkssection-div-343", children: _jsx("span", { className: `${iconColor}`, "aria-hidden": "true", children: step.renderIcon({ className: "w-6 h-6" }) }) })), _jsx(Heading, { level: 3, className: `relative z-10 text-base font-semibold ${THEME_CONSTANTS.themed.textPrimary} mb-2`, children: step.title }), _jsx(Text, { className: `relative z-10 text-sm ${THEME_CONSTANTS.themed.textSecondary} leading-relaxed`, children: step.desc })] }));
|
|
16
18
|
}
|
|
17
19
|
// --- Section -----------------------------------------------------------------
|
|
@@ -32,5 +34,5 @@ export function HowItWorksSection({ title, subtitle, pillLabel, ctaLabel, onCtaC
|
|
|
32
34
|
observer.observe(el);
|
|
33
35
|
return () => observer.disconnect();
|
|
34
36
|
}, []);
|
|
35
|
-
return (_jsx(Section, { ref: sectionRef, className: `p-8 ${themed.bgPrimary} ${className}`, children: _jsxs(Div, { className: "max-w-6xl mx-auto", children: [_jsxs("div", { className: `text-center mb-12 transition-all duration-700 ${visible ?
|
|
37
|
+
return (_jsx(Section, { ref: sectionRef, className: `p-8 ${themed.bgPrimary} ${className}`, children: _jsxs(Div, { className: "max-w-6xl mx-auto", children: [_jsxs("div", { className: `text-center mb-12 transition-all duration-700 ${visible ? CLS_VISIBLE : "opacity-0 translate-y-4"}`, "data-section": "howitworkssection-div-344", children: [pillLabel && (_jsx("div", { className: "inline-block mb-4 inline-flex items-center gap-2 rounded-full border border-primary-500/30 bg-primary-500/10 px-5 py-1.5 text-xs font-medium tracking-[0.2em] uppercase text-primary-700 dark:text-primary-400 backdrop-blur-sm", "data-section": "howitworkssection-div-345", children: pillLabel })), _jsx(Heading, { level: 2, className: `text-3xl md:text-4xl font-bold ${themed.textPrimary} mb-3`, children: title }), subtitle && (_jsx(Text, { className: `text-base ${themed.textSecondary} max-w-xl mx-auto`, children: subtitle }))] }), _jsx(Grid, { gap: "lg", className: "grid-cols-1 md:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-3 mb-10", children: steps.map((step, i) => (_jsx(StepCard, { step: step, visible: visible, delay: i * 150 }, step.number))) }), ctaLabel && onCtaClick && (_jsx("div", { className: `text-center transition-all duration-700 delay-500 ${visible ? CLS_VISIBLE : "opacity-0 translate-y-4"}`, "data-section": "howitworkssection-div-346", children: _jsx(Button, { variant: "primary", size: "lg", onClick: onCtaClick, children: ctaLabel }) }))] }) }));
|
|
36
38
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Heading, Section, Text } from "../../../ui";
|
|
3
3
|
import { THEME_CONSTANTS } from "../../../tokens";
|
|
4
4
|
import { SocialPostCard } from "./SocialPostCard";
|
|
@@ -102,5 +102,5 @@ export async function SocialFeedSection(config) {
|
|
|
102
102
|
: layout === "masonry"
|
|
103
103
|
? "break-inside-avoid"
|
|
104
104
|
: "";
|
|
105
|
-
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsxs("div", { className: "w-full max-w-7xl mx-auto px-4", children: [_jsxs("div", { className: "mb-8 flex items-end justify-between gap-4", children: [_jsxs(
|
|
105
|
+
return (_jsx(Section, { className: `py-12 ${themed.bgPrimary}`, children: _jsxs("div", { className: "w-full max-w-7xl mx-auto px-4", children: [_jsxs("div", { className: "mb-8 flex items-end justify-between gap-4", children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 2, className: "mb-1", children: title || `${PLATFORM_LABELS[platform]} Feed` }), subtitle && (_jsx(Text, { size: "sm", variant: "muted", children: subtitle }))] }), profileUrl && (_jsxs("a", { href: profileUrl, target: "_blank", rel: "noopener noreferrer", className: "shrink-0 text-sm font-medium text-[var(--appkit-color-primary)] hover:opacity-80", children: ["Follow on ", PLATFORM_LABELS[platform], " \u2192"] }))] }), error ? (_jsx("div", { className: "py-12 text-center text-zinc-400 text-sm", children: error })) : posts.length === 0 ? (_jsx(SocialFeedEmpty, { platform: platform })) : (_jsx("div", { className: gridClass, children: posts.slice(0, count).map((post) => (_jsx("div", { className: cardClass, children: _jsx(SocialPostCard, { post: post, showCaption: showCaption, showStats: showStats }) }, post.id))) }))] }) }));
|
|
106
106
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Text } from "../../../ui";
|
|
3
4
|
// --- Platform brand colours & icons ------------------------------------------
|
|
4
5
|
const PLATFORM_META = {
|
|
5
6
|
instagram: {
|
|
@@ -43,12 +44,12 @@ function YouTubeCard({ post, showCaption }) {
|
|
|
43
44
|
const thumbnail = `https://img.youtube.com/vi/${post.videoId}/maxresdefault.jpg`;
|
|
44
45
|
const href = `https://youtu.be/${post.videoId}`;
|
|
45
46
|
const meta = PLATFORM_META.youtube;
|
|
46
|
-
return (_jsxs("a", { href: href, target: "_blank", rel: "noopener noreferrer", className: "group relative block aspect-video w-full overflow-hidden rounded-xl bg-zinc-900 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--appkit-color-youtube,#FF0000)]", "aria-label": post.caption ?? `Watch on YouTube`, children: [_jsx("img", { src: thumbnail, alt: post.caption ?? "YouTube video", className: "h-full w-full object-cover transition-transform duration-300 group-hover:scale-105", loading: "lazy" }), _jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "flex h-14 w-14 items-center justify-center rounded-full bg-[var(--appkit-color-youtube,#FF0000)] shadow-lg transition-transform duration-200 group-hover:scale-110", children: _jsx("svg", { className: "ml-1 h-6 w-6 text-white", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M8 5v14l11-7z" }) }) }) }), _jsxs("div", { className: `absolute right-2 top-2 flex items-center gap-1 rounded px-1.5 py-1 text-xs font-medium text-white ${meta.colorClass}`, children: [meta.icon, _jsx("span", { className: "hidden sm:inline", children: meta.label })] }), post.channelName && (_jsx("div", { className: "absolute bottom-2 left-2 rounded bg-black/60 px-2 py-0.5 text-xs text-white backdrop-blur-sm", children: post.channelName })), showCaption && post.caption && (_jsx("div", { className: "absolute inset-0 flex flex-col justify-end bg-black/60 p-3 opacity-0 transition-opacity duration-200 group-hover:opacity-100", children: _jsx(
|
|
47
|
+
return (_jsxs("a", { href: href, target: "_blank", rel: "noopener noreferrer", className: "group relative block aspect-video w-full overflow-hidden rounded-xl bg-zinc-900 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--appkit-color-youtube,#FF0000)]", "aria-label": post.caption ?? `Watch on YouTube`, children: [_jsx("img", { src: thumbnail, alt: post.caption ?? "YouTube video", className: "h-full w-full object-cover transition-transform duration-300 group-hover:scale-105", loading: "lazy" }), _jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "flex h-14 w-14 items-center justify-center rounded-full bg-[var(--appkit-color-youtube,#FF0000)] shadow-lg transition-transform duration-200 group-hover:scale-110", children: _jsx("svg", { className: "ml-1 h-6 w-6 text-white", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M8 5v14l11-7z" }) }) }) }), _jsxs("div", { className: `absolute right-2 top-2 flex items-center gap-1 rounded px-1.5 py-1 text-xs font-medium text-white ${meta.colorClass}`, children: [meta.icon, _jsx("span", { className: "hidden sm:inline", children: meta.label })] }), post.channelName && (_jsx("div", { className: "absolute bottom-2 left-2 rounded bg-black/60 px-2 py-0.5 text-xs text-white backdrop-blur-sm", children: post.channelName })), showCaption && post.caption && (_jsx("div", { className: "absolute inset-0 flex flex-col justify-end bg-black/60 p-3 opacity-0 transition-opacity duration-200 group-hover:opacity-100", children: _jsx(Text, { className: "line-clamp-2 text-xs text-white", children: post.caption }) }))] }));
|
|
47
48
|
}
|
|
48
49
|
export function SocialPostCard({ post, showCaption = true, showStats = true }) {
|
|
49
50
|
if (post.platform === "youtube") {
|
|
50
51
|
return _jsx(YouTubeCard, { post: post, showCaption: showCaption });
|
|
51
52
|
}
|
|
52
53
|
const meta = PLATFORM_META[post.platform];
|
|
53
|
-
return (_jsxs("a", { href: post.permalink, target: "_blank", rel: "noopener noreferrer", className: "group relative block aspect-square overflow-hidden rounded-xl bg-zinc-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--appkit-color-primary)] dark:bg-zinc-800", "aria-label": post.caption ?? `View on ${meta.label}`, children: [post.imageUrl ? (_jsx("img", { src: post.imageUrl, alt: post.caption ?? `${meta.label} post`, className: "h-full w-full object-cover transition-transform duration-300 group-hover:scale-105", loading: "lazy" })) : (_jsx("div", { className: "flex h-full w-full items-center justify-center bg-zinc-200 dark:bg-zinc-700", children: _jsx("span", { className: "text-sm text-zinc-400", children: "No preview" }) })), post.mediaType === "video" && (_jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-black/50 backdrop-blur-sm", children: _jsx("svg", { className: "ml-1 h-5 w-5 text-white", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M8 5v14l11-7z" }) }) }) })), post.mediaType === "carousel" && (_jsx("div", { className: "pointer-events-none absolute right-2 top-2", children: _jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded bg-black/50 backdrop-blur-sm", children: _jsxs("svg", { className: "h-3.5 w-3.5 text-white", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "2", y: "3", width: "15", height: "15", rx: "2" }), _jsx("path", { d: "M7 8h14M7 12h14M7 16h14" })] }) }) })), _jsxs("div", { className: `absolute left-2 top-2 flex items-center gap-1 rounded px-1.5 py-1 text-xs font-medium text-white ${meta.colorClass}`, children: [meta.icon, _jsx("span", { className: "hidden sm:inline", children: meta.label })] }), _jsxs("div", { className: "pointer-events-none absolute inset-0 flex flex-col justify-end bg-black/70 p-3 opacity-0 transition-opacity duration-200 group-hover:opacity-100", children: [showCaption && post.caption && (_jsx(
|
|
54
|
+
return (_jsxs("a", { href: post.permalink, target: "_blank", rel: "noopener noreferrer", className: "group relative block aspect-square overflow-hidden rounded-xl bg-zinc-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--appkit-color-primary)] dark:bg-zinc-800", "aria-label": post.caption ?? `View on ${meta.label}`, children: [post.imageUrl ? (_jsx("img", { src: post.imageUrl, alt: post.caption ?? `${meta.label} post`, className: "h-full w-full object-cover transition-transform duration-300 group-hover:scale-105", loading: "lazy" })) : (_jsx("div", { className: "flex h-full w-full items-center justify-center bg-zinc-200 dark:bg-zinc-700", children: _jsx("span", { className: "text-sm text-zinc-400", children: "No preview" }) })), post.mediaType === "video" && (_jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-black/50 backdrop-blur-sm", children: _jsx("svg", { className: "ml-1 h-5 w-5 text-white", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M8 5v14l11-7z" }) }) }) })), post.mediaType === "carousel" && (_jsx("div", { className: "pointer-events-none absolute right-2 top-2", children: _jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded bg-black/50 backdrop-blur-sm", children: _jsxs("svg", { className: "h-3.5 w-3.5 text-white", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "2", y: "3", width: "15", height: "15", rx: "2" }), _jsx("path", { d: "M7 8h14M7 12h14M7 16h14" })] }) }) })), _jsxs("div", { className: `absolute left-2 top-2 flex items-center gap-1 rounded px-1.5 py-1 text-xs font-medium text-white ${meta.colorClass}`, children: [meta.icon, _jsx("span", { className: "hidden sm:inline", children: meta.label })] }), _jsxs("div", { className: "pointer-events-none absolute inset-0 flex flex-col justify-end bg-black/70 p-3 opacity-0 transition-opacity duration-200 group-hover:opacity-100", children: [showCaption && post.caption && (_jsx(Text, { className: "mb-2 line-clamp-3 text-xs text-white", children: post.caption })), showStats && (_jsxs("div", { className: "flex items-center gap-3 text-xs text-white/80", children: [post.stats.likes != null && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx("svg", { className: "h-3 w-3", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" }) }), formatCount(post.stats.likes)] })), post.stats.views != null && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx("svg", { className: "h-3 w-3", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" }) }), formatCount(post.stats.views)] })), post.stats.comments != null && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx("svg", { className: "h-3 w-3", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }), formatCount(post.stats.comments)] }))] }))] })] }));
|
|
54
55
|
}
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
function clamp(n, min, max) {
|
|
3
3
|
return Math.max(min, Math.min(max, n));
|
|
4
4
|
}
|
|
5
|
+
function isVideoOrReels(postType) {
|
|
6
|
+
return ["videos", "reels"].includes(postType);
|
|
7
|
+
}
|
|
5
8
|
// --- Instagram (Meta Graph API v19) ------------------------------------------
|
|
6
9
|
export async function fetchInstagramPosts(handle, postType, count, accessToken) {
|
|
7
10
|
const fields = "id,caption,media_type,media_url,thumbnail_url,permalink,timestamp,like_count,comments_count";
|
|
@@ -19,7 +22,7 @@ export async function fetchInstagramPosts(handle, postType, count, accessToken)
|
|
|
19
22
|
const m = item;
|
|
20
23
|
if (postType === "images")
|
|
21
24
|
return m.media_type === "IMAGE";
|
|
22
|
-
if (postType
|
|
25
|
+
if (isVideoOrReels(postType))
|
|
23
26
|
return m.media_type === "VIDEO";
|
|
24
27
|
return true;
|
|
25
28
|
})
|
|
@@ -65,7 +68,7 @@ export async function fetchFacebookPosts(handle, postType, count, accessToken) {
|
|
|
65
68
|
const mtype = attachType?.media_type;
|
|
66
69
|
if (postType === "images")
|
|
67
70
|
return mtype !== "video";
|
|
68
|
-
if (postType
|
|
71
|
+
if (isVideoOrReels(postType))
|
|
69
72
|
return mtype === "video";
|
|
70
73
|
return true;
|
|
71
74
|
})
|
|
@@ -155,7 +158,7 @@ async function getDeviantArtToken(clientId, clientSecret) {
|
|
|
155
158
|
return json.access_token;
|
|
156
159
|
}
|
|
157
160
|
export async function fetchDeviantArtPosts(handle, postType, count, clientId, clientSecret) {
|
|
158
|
-
if (postType
|
|
161
|
+
if (isVideoOrReels(postType))
|
|
159
162
|
return [];
|
|
160
163
|
const token = await getDeviantArtToken(clientId, clientSecret);
|
|
161
164
|
const url = new URL("https://www.deviantart.com/api/v1/oauth2/gallery/all");
|
|
@@ -18,7 +18,7 @@ export interface AppLayoutShellSidebarSection {
|
|
|
18
18
|
export interface AppLayoutShellSidebarAction {
|
|
19
19
|
href: string;
|
|
20
20
|
label: string;
|
|
21
|
-
variant?: "
|
|
21
|
+
variant?: "primary" | "outline";
|
|
22
22
|
}
|
|
23
23
|
export interface AppLayoutShellProps {
|
|
24
24
|
children: React.ReactNode;
|
|
@@ -88,6 +88,12 @@ export interface AppLayoutShellProps {
|
|
|
88
88
|
logout?: string;
|
|
89
89
|
};
|
|
90
90
|
eventBannerSlot?: React.ReactNode;
|
|
91
|
+
/**
|
|
92
|
+
* Override className for the main content wrapper div.
|
|
93
|
+
* When set, replaces the default `container mx-auto w-full max-w-screen-2xl px-4 py-6 …`
|
|
94
|
+
* Use `"w-full"` for dashboard layouts that provide their own padding via DashboardLayoutClient.
|
|
95
|
+
*/
|
|
96
|
+
contentClassName?: string;
|
|
91
97
|
lightBackground?: {
|
|
92
98
|
type: "color" | "image" | "gradient" | "video";
|
|
93
99
|
value: string;
|
|
@@ -107,4 +113,4 @@ export interface AppLayoutShellProps {
|
|
|
107
113
|
};
|
|
108
114
|
};
|
|
109
115
|
}
|
|
110
|
-
export declare function AppLayoutShell({ children, navItems, sidebarItems, sidebarSections, sidebarPrimaryActions, sidebarTitle, hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle, suppressDashboardNav, hideSidebarToggle, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar, sidebarProfileLabels, eventBannerSlot, lightBackground, darkBackground, }: AppLayoutShellProps): import("react/jsx-runtime").JSX.Element;
|
|
116
|
+
export declare function AppLayoutShell({ children, navItems, sidebarItems, sidebarSections, sidebarPrimaryActions, sidebarTitle, hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle, suppressDashboardNav, hideSidebarToggle, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar, sidebarProfileLabels, eventBannerSlot, contentClassName, lightBackground, darkBackground, }: AppLayoutShellProps): import("react/jsx-runtime").JSX.Element;
|