@mohasinac/appkit 4.59.0 → 4.60.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/.build-stamp.json +3 -3
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +62 -5
- package/dist/_internal/client/features/maintenance/views/MaintenanceDashboardView.js +2 -2
- package/dist/_internal/server/features/brands/actions.js +78 -4
- package/dist/_internal/server/features/checkout/actions.d.ts +36 -13
- package/dist/_internal/server/features/checkout/actions.js +668 -183
- package/dist/_internal/server/features/checkout/supplier-identity.js +18 -1
- package/dist/_internal/server/features/gateway-events/index.d.ts +10 -0
- package/dist/_internal/server/features/gateway-events/index.js +10 -0
- package/dist/_internal/server/features/gateway-events/ingest.d.ts +127 -0
- package/dist/_internal/server/features/gateway-events/ingest.js +188 -0
- package/dist/_internal/server/features/gateway-events/redact.d.ts +66 -0
- package/dist/_internal/server/features/gateway-events/redact.js +151 -0
- package/dist/_internal/server/features/grievance/actions.d.ts +63 -0
- package/dist/_internal/server/features/grievance/actions.js +173 -0
- package/dist/_internal/server/features/grievance/index.d.ts +8 -0
- package/dist/_internal/server/features/grievance/index.js +8 -0
- package/dist/_internal/server/features/grouped/data.js +28 -3
- package/dist/_internal/server/features/lottery/actions.js +99 -4
- package/dist/_internal/server/features/order-completion/actions.d.ts +92 -0
- package/dist/_internal/server/features/order-completion/actions.js +336 -0
- package/dist/_internal/server/features/order-completion/index.d.ts +7 -0
- package/dist/_internal/server/features/order-completion/index.js +7 -0
- package/dist/_internal/server/features/orders/actions.d.ts +13 -0
- package/dist/_internal/server/features/orders/actions.js +56 -2
- package/dist/_internal/server/features/orders/adapters.d.ts +20 -2
- package/dist/_internal/server/features/orders/adapters.js +44 -0
- package/dist/_internal/server/features/orders/cancellation-refund.d.ts +116 -0
- package/dist/_internal/server/features/orders/cancellation-refund.js +466 -0
- package/dist/_internal/server/features/orders/index.d.ts +2 -1
- package/dist/_internal/server/features/orders/index.js +1 -1
- package/dist/_internal/server/features/orders/service.d.ts +60 -0
- package/dist/_internal/server/features/orders/service.js +74 -0
- package/dist/_internal/server/features/payment-cases/disputes.d.ts +76 -0
- package/dist/_internal/server/features/payment-cases/disputes.js +241 -0
- package/dist/_internal/server/features/payment-cases/index.d.ts +9 -0
- package/dist/_internal/server/features/payment-cases/index.js +9 -0
- package/dist/_internal/server/features/payouts/actions.d.ts +28 -3
- package/dist/_internal/server/features/payouts/actions.js +84 -10
- package/dist/_internal/server/features/points/adjust.d.ts +61 -0
- package/dist/_internal/server/features/points/adjust.js +121 -0
- package/dist/_internal/server/features/points/award.d.ts +65 -0
- package/dist/_internal/server/features/points/award.js +145 -0
- package/dist/_internal/server/features/price-index/market.d.ts +33 -0
- package/dist/_internal/server/features/price-index/market.js +54 -1
- package/dist/_internal/server/features/products/data.js +40 -22
- package/dist/_internal/server/features/protection-claims/actions.d.ts +72 -0
- package/dist/_internal/server/features/protection-claims/actions.js +228 -0
- package/dist/_internal/server/features/protection-claims/index.d.ts +8 -0
- package/dist/_internal/server/features/protection-claims/index.js +8 -0
- package/dist/_internal/server/features/refunds/actions.d.ts +20 -0
- package/dist/_internal/server/features/refunds/actions.js +259 -17
- package/dist/_internal/server/features/refunds/capacity.d.ts +29 -0
- package/dist/_internal/server/features/refunds/capacity.js +37 -0
- package/dist/_internal/server/features/reviews/actions.js +3 -2
- package/dist/_internal/server/features/search/index-build/sources.js +20 -1
- package/dist/_internal/server/features/shipping/reconcile.d.ts +10 -1
- package/dist/_internal/server/features/shipping/reconcile.js +34 -3
- package/dist/_internal/server/features/shipping/reimbursement.d.ts +117 -0
- package/dist/_internal/server/features/shipping/reimbursement.js +223 -0
- package/dist/_internal/server/features/stores/tabs.d.ts +19 -4
- package/dist/_internal/server/features/stores/tabs.js +24 -4
- package/dist/_internal/server/functions/https.d.ts +31 -1
- package/dist/_internal/server/functions/https.js +52 -1
- package/dist/_internal/server/functions/scheduled.d.ts +72 -1
- package/dist/_internal/server/functions/scheduled.js +124 -1
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +62 -16
- package/dist/_internal/server/jobs/core/boxRollupReconcile.d.ts +46 -0
- package/dist/_internal/server/jobs/core/boxRollupReconcile.js +142 -0
- package/dist/_internal/server/jobs/core/dailyDataCleanup.js +149 -1
- package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +14 -0
- package/dist/_internal/server/jobs/core/dailyStatusDigest.js +79 -1
- package/dist/_internal/server/jobs/core/index.d.ts +2 -0
- package/dist/_internal/server/jobs/core/index.js +2 -0
- package/dist/_internal/server/jobs/core/marketPriceRollup.d.ts +64 -0
- package/dist/_internal/server/jobs/core/marketPriceRollup.js +153 -0
- package/dist/_internal/server/jobs/core/obligationSweep.d.ts +36 -0
- package/dist/_internal/server/jobs/core/obligationSweep.js +503 -0
- package/dist/_internal/server/jobs/core/paymentReconcile.d.ts +79 -0
- package/dist/_internal/server/jobs/core/paymentReconcile.js +614 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +34 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +35 -4
- package/dist/_internal/server/jobs/handlers/boxRollupReconcile.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/boxRollupReconcile.js +15 -0
- package/dist/_internal/server/jobs/handlers/countersReconcileNow.d.ts +65 -0
- package/dist/_internal/server/jobs/handlers/countersReconcileNow.js +89 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +5 -0
- package/dist/_internal/server/jobs/handlers/index.js +5 -0
- package/dist/_internal/server/jobs/handlers/marketPriceRollup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/marketPriceRollup.js +2 -0
- package/dist/_internal/server/jobs/handlers/obligationSweep.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/obligationSweep.js +15 -0
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +30 -1
- package/dist/_internal/server/jobs/handlers/paymentReconcile.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/paymentReconcile.js +6 -0
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +71 -0
- package/dist/_internal/shared/checkout/coupon-discount.d.ts +73 -0
- package/dist/_internal/shared/checkout/coupon-discount.js +103 -0
- package/dist/_internal/shared/checkout/lanes.d.ts +42 -0
- package/dist/_internal/shared/checkout/lanes.js +46 -0
- package/dist/_internal/shared/checkout/order-math.d.ts +149 -1
- package/dist/_internal/shared/checkout/order-math.js +251 -3
- package/dist/_internal/shared/checkout/refundable-base.d.ts +116 -0
- package/dist/_internal/shared/checkout/refundable-base.js +122 -0
- package/dist/_internal/shared/features/auctions/config.d.ts +14 -1
- package/dist/_internal/shared/features/auctions/config.js +30 -1
- package/dist/_internal/shared/features/brands/schema.d.ts +42 -0
- package/dist/_internal/shared/features/brands/schema.js +18 -0
- package/dist/_internal/shared/features/orders/refund-copy.d.ts +22 -0
- package/dist/_internal/shared/features/orders/refund-copy.js +34 -0
- package/dist/_internal/shared/features/print/label-profiles.d.ts +198 -0
- package/dist/_internal/shared/features/print/label-profiles.js +350 -0
- package/dist/_internal/shared/features/products/to-product-item.js +33 -5
- package/dist/_internal/shared/fees/calculator.d.ts +31 -2
- package/dist/_internal/shared/fees/calculator.js +103 -5
- package/dist/_internal/shared/fees/india-states.d.ts +195 -0
- package/dist/_internal/shared/fees/india-states.js +190 -0
- package/dist/_internal/shared/fees/payout-hold.d.ts +80 -0
- package/dist/_internal/shared/fees/payout-hold.js +74 -0
- package/dist/_internal/shared/obligations/deadlines.d.ts +94 -0
- package/dist/_internal/shared/obligations/deadlines.js +155 -0
- package/dist/_internal/shared/shipping/quote.d.ts +96 -0
- package/dist/_internal/shared/shipping/quote.js +67 -0
- package/dist/_internal/shared/time/business-days.d.ts +91 -0
- package/dist/_internal/shared/time/business-days.js +185 -0
- package/dist/cli/index.js +0 -2
- package/dist/client.d.ts +10 -4
- package/dist/client.js +29 -3
- package/dist/configs/tailwind.d.ts +0 -12
- package/dist/configs/tailwind.js +28 -15
- package/dist/constants/api-endpoints.d.ts +51 -9
- package/dist/constants/api-endpoints.js +23 -7
- package/dist/constants/index.d.ts +1 -1
- package/dist/constants/index.js +1 -1
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/payment.d.ts +131 -0
- package/dist/features/about/components/AboutView.js +1 -1
- package/dist/features/about/components/DeveloperView.js +5 -2
- package/dist/features/about/components/FAQPageView.js +2 -1
- package/dist/features/about/components/FeesView.js +2 -1
- package/dist/features/about/components/HelpPageView.js +2 -1
- package/dist/features/about/components/HowAuctionsWorkView.js +2 -1
- package/dist/features/about/components/HowCheckoutWorksView.js +2 -1
- package/dist/features/about/components/HowEmiWorksView.js +2 -1
- package/dist/features/about/components/HowOffersWorkView.js +2 -1
- package/dist/features/about/components/HowOrdersWorkView.js +2 -1
- package/dist/features/about/components/HowPayoutsWorkView.js +2 -1
- package/dist/features/about/components/HowPreOrdersWorkView.js +2 -1
- package/dist/features/about/components/HowReviewsWorkView.js +2 -1
- package/dist/features/about/components/PolicyPageView.js +2 -1
- package/dist/features/about/components/ProseHero.d.ts +73 -0
- package/dist/features/about/components/ProseHero.js +18 -0
- package/dist/features/about/components/SecurityPrivacyView.js +2 -1
- package/dist/features/about/components/ShippingPolicyView.js +2 -1
- package/dist/features/about/components/TrackOrderView.js +2 -1
- package/dist/features/about/components/UnauthorizedView.js +1 -1
- package/dist/features/about/index.d.ts +2 -0
- package/dist/features/about/index.js +5 -0
- package/dist/features/account/actions/address-actions.d.ts +26 -2
- package/dist/features/account/actions/address-actions.js +25 -1
- package/dist/features/account/components/BuyerShoppingGuideView.js +1 -1
- package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
- package/dist/features/account/components/UserOrdersView.js +17 -0
- package/dist/features/account/components/UserSidebar.js +1 -1
- package/dist/features/account/hooks/useNotifications.js +29 -0
- package/dist/features/admin/actions/admin-coupon-actions.js +36 -0
- package/dist/features/admin/components/AdminBeysView.js +2 -2
- package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
- package/dist/features/admin/components/AdminBrandEditorView.js +32 -2
- package/dist/features/admin/components/AdminBundleEditorView.js +1 -1
- package/dist/features/admin/components/AdminCarouselEditorView.js +1 -1
- package/dist/features/admin/components/AdminCategoriesView.js +1 -1
- package/dist/features/admin/components/AdminCategoryEditorView.js +73 -17
- package/dist/features/admin/components/AdminContactEditorView.js +1 -1
- package/dist/features/admin/components/AdminCouponEditorView.js +26 -1
- package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
- package/dist/features/admin/components/AdminFaqsView.js +2 -2
- package/dist/features/admin/components/AdminGatewayEventsView.d.ts +54 -0
- package/dist/features/admin/components/AdminGatewayEventsView.js +209 -0
- package/dist/features/admin/components/AdminGuideHubView.js +1 -1
- package/dist/features/admin/components/AdminMoneyCasesView.d.ts +60 -0
- package/dist/features/admin/components/AdminMoneyCasesView.js +287 -0
- package/dist/features/admin/components/AdminPartsView.js +2 -2
- package/dist/features/admin/components/AdminProductsView.js +75 -4
- package/dist/features/admin/components/AdminSidebar.js +2 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +65 -7
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +2 -0
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketsView.js +2 -2
- package/dist/features/admin/components/AdminTesterChecklistView.js +2 -2
- package/dist/features/admin/components/AdminUsersView.js +72 -1
- package/dist/features/admin/components/AdminViewCards.d.ts +3 -1
- package/dist/features/admin/components/AdminViewCards.js +4 -4
- package/dist/features/admin/components/DataListingView.d.ts +28 -0
- package/dist/features/admin/components/DataListingView.js +175 -14
- package/dist/features/admin/components/DataTable.d.ts +12 -1
- package/dist/features/admin/components/DataTable.js +3 -3
- package/dist/features/admin/components/OwnerQuickActions.d.ts +1 -1
- package/dist/features/admin/components/OwnerQuickActions.js +60 -2
- package/dist/features/admin/components/RecordOwnerQuickActions.d.ts +1 -1
- package/dist/features/admin/components/RecordOwnerQuickActions.js +61 -14
- package/dist/features/admin/components/analytics/AdminStatCard.d.ts +35 -1
- package/dist/features/admin/components/analytics/AdminStatCard.js +77 -2
- package/dist/features/admin/components/index.d.ts +4 -0
- package/dist/features/admin/components/index.js +6 -0
- package/dist/features/admin/constants/filter-tabs.d.ts +156 -0
- package/dist/features/admin/constants/filter-tabs.js +106 -0
- package/dist/features/admin/repository/site-settings.repository.d.ts +22 -0
- package/dist/features/admin/repository/site-settings.repository.js +82 -1
- package/dist/features/admin/schemas/admin-editor-forms.d.ts +21 -0
- package/dist/features/admin/schemas/admin-editor-forms.js +44 -0
- package/dist/features/admin/schemas/firestore.js +5 -1
- package/dist/features/admin/schemas/site-settings-form.js +30 -1
- package/dist/features/auctions/actions/bid-actions.js +13 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +2 -2
- package/dist/features/auctions/components/AuctionDetailPageView.js +3 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -0
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +5 -3
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +8 -1
- package/dist/features/auctions/components/PlaceBidFormClient.js +2 -2
- package/dist/features/audit-log/schemas/firestore.d.ts +28 -0
- package/dist/features/audit-log/schemas/firestore.js +14 -0
- package/dist/features/auth/permissions/constants.d.ts +17 -1
- package/dist/features/auth/permissions/constants.js +18 -0
- package/dist/features/blog/components/BlogPostView.js +1 -1
- package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +1 -1
- package/dist/features/categories/api/[id]/description-template/route.js +107 -1
- package/dist/features/categories/components/BrandDetailPageView.js +2 -2
- package/dist/features/categories/components/BreadcrumbTrail.js +7 -1
- package/dist/features/categories/components/BundleDetailView.js +1 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
- package/dist/features/categories/components/CategoryForm.js +12 -1
- package/dist/features/categories/components/CategoryTemplatePicker.js +38 -5
- package/dist/features/categories/repository/market-price-index.repository.d.ts +123 -0
- package/dist/features/categories/repository/market-price-index.repository.js +105 -0
- package/dist/features/categories/repository/price-observation.repository.d.ts +166 -0
- package/dist/features/categories/repository/price-observation.repository.js +132 -0
- package/dist/features/events/components/EventSaleBanner.js +1 -1
- package/dist/features/events/components/EventStatusBadge.js +1 -1
- package/dist/features/faq/components/FAQAccordion.js +2 -1
- package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
- package/dist/features/faq/components/FAQHelpfulButtons.js +4 -4
- package/dist/features/faq/components/RelatedFAQs.js +1 -1
- package/dist/features/filters/FilterFacetSection.js +1 -1
- package/dist/features/filters/SwitchFilter.js +1 -1
- package/dist/features/gateway-events/repository/gateway-events.repository.d.ts +117 -0
- package/dist/features/gateway-events/repository/gateway-events.repository.js +274 -0
- package/dist/features/gateway-events/schemas/firestore.d.ts +217 -0
- package/dist/features/gateway-events/schemas/firestore.js +125 -0
- package/dist/features/gateway-events/schemas/index.d.ts +81 -0
- package/dist/features/gateway-events/schemas/index.js +79 -0
- package/dist/features/grouped/components/GroupedListingDetailView.js +1 -1
- package/dist/features/homepage/components/AnnouncementBar.js +37 -1
- package/dist/features/homepage/components/AnnouncementBar.style.css +30 -0
- package/dist/features/homepage/components/BrandsSection.js +1 -1
- package/dist/features/homepage/components/CTABannerSection.js +1 -1
- package/dist/features/homepage/components/FeaturedBundlesSection.js +14 -24
- package/dist/features/homepage/components/HeroCarousel.js +2 -2
- package/dist/features/homepage/components/SocialPostCard.js +1 -1
- package/dist/features/inventory/components/AdminMoveLedgerView.d.ts +7 -0
- package/dist/features/inventory/components/AdminMoveLedgerView.js +157 -0
- package/dist/features/inventory/components/AdminStorageBoxesView.d.ts +11 -0
- package/dist/features/inventory/components/AdminStorageBoxesView.js +168 -0
- package/dist/features/inventory/components/ReceiveStationView.d.ts +39 -0
- package/dist/features/inventory/components/ReceiveStationView.js +413 -0
- package/dist/features/inventory/components/operator-message.d.ts +29 -0
- package/dist/features/inventory/components/operator-message.js +41 -0
- package/dist/features/inventory/index.d.ts +13 -0
- package/dist/features/inventory/index.js +28 -0
- package/dist/features/inventory/repository/inventory-movements.repository.d.ts +97 -0
- package/dist/features/inventory/repository/inventory-movements.repository.js +186 -0
- package/dist/features/inventory/repository/inventory-placements.repository.d.ts +179 -0
- package/dist/features/inventory/repository/inventory-placements.repository.js +345 -0
- package/dist/features/inventory/repository/storage-boxes.repository.d.ts +83 -0
- package/dist/features/inventory/repository/storage-boxes.repository.js +127 -0
- package/dist/features/inventory/schemas/firestore.d.ts +197 -0
- package/dist/features/inventory/schemas/firestore.js +159 -0
- package/dist/features/layout/AppLayoutShell.d.ts +12 -1
- package/dist/features/layout/AppLayoutShell.js +25 -12
- package/dist/features/layout/AutoBreadcrumbs.js +162 -3
- package/dist/features/layout/AutoBreadcrumbs.style.css +45 -0
- package/dist/features/layout/BottomNavbar.d.ts +1 -1
- package/dist/features/layout/BottomNavbar.js +2 -2
- package/dist/features/media/MediaAvatar.js +1 -1
- package/dist/features/media/MediaImage.d.ts +24 -4
- package/dist/features/media/MediaImage.js +44 -4
- package/dist/features/media/MediaLightbox.js +1 -1
- package/dist/features/media/modals/ImageCropModal.js +1 -1
- package/dist/features/media/modals/ImageEditor.js +1 -1
- package/dist/features/media/upload/MediaUploadField.js +91 -3
- package/dist/features/obligations/constants/policies.d.ts +92 -0
- package/dist/features/obligations/constants/policies.js +378 -0
- package/dist/features/obligations/repository/obligations.repository.d.ts +68 -0
- package/dist/features/obligations/repository/obligations.repository.js +158 -0
- package/dist/features/obligations/schemas/firestore.d.ts +160 -0
- package/dist/features/obligations/schemas/firestore.js +87 -0
- package/dist/features/orders/actions/order-actions.d.ts +43 -4
- package/dist/features/orders/actions/order-actions.js +60 -3
- package/dist/features/orders/actions/refund-actions.js +70 -10
- package/dist/features/orders/components/OrderCompletionPanel.d.ts +27 -0
- package/dist/features/orders/components/OrderCompletionPanel.js +192 -0
- package/dist/features/orders/components/OrdersList.js +2 -2
- package/dist/features/orders/components/RefundHistoryTable.js +3 -1
- package/dist/features/orders/components/index.d.ts +2 -0
- package/dist/features/orders/components/index.js +6 -0
- package/dist/features/orders/constants/transitions.d.ts +59 -0
- package/dist/features/orders/constants/transitions.js +104 -0
- package/dist/features/orders/repository/orders.repository.d.ts +109 -6
- package/dist/features/orders/repository/orders.repository.js +464 -21
- package/dist/features/orders/schemas/firestore.d.ts +270 -0
- package/dist/features/orders/schemas/firestore.js +24 -0
- package/dist/features/orders/schemas/index.d.ts +61 -0
- package/dist/features/orders/schemas/index.js +22 -0
- package/dist/features/orders/types/index.d.ts +79 -0
- package/dist/features/parts/components/PartsIndexPageView.js +8 -1
- package/dist/features/payment-cases/repository/payment-cases.repository.d.ts +170 -0
- package/dist/features/payment-cases/repository/payment-cases.repository.js +342 -0
- package/dist/features/payment-cases/schemas/firestore.d.ts +229 -0
- package/dist/features/payment-cases/schemas/firestore.js +105 -0
- package/dist/features/payment-cases/schemas/resolve-form.d.ts +97 -0
- package/dist/features/payment-cases/schemas/resolve-form.js +114 -0
- package/dist/features/payments/repository/payout.repository.d.ts +0 -1
- package/dist/features/payments/repository/payout.repository.js +0 -1
- package/dist/features/points/repository/points.repository.d.ts +122 -0
- package/dist/features/points/repository/points.repository.js +304 -1
- package/dist/features/points/schemas/adjust-form.d.ts +58 -0
- package/dist/features/points/schemas/adjust-form.js +63 -0
- package/dist/features/points/schemas/firestore.d.ts +108 -1
- package/dist/features/points/schemas/firestore.js +84 -0
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -3
- package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
- package/dist/features/price-index/components/PriceIndexToolView.d.ts +23 -4
- package/dist/features/price-index/components/PriceIndexToolView.js +71 -6
- package/dist/features/price-index/market-stats.d.ts +82 -0
- package/dist/features/price-index/market-stats.js +230 -0
- package/dist/features/print/components/BoxLabelPrintView.d.ts +25 -0
- package/dist/features/print/components/BoxLabelPrintView.js +66 -0
- package/dist/features/print/components/LabelProfilePicker.d.ts +13 -0
- package/dist/features/print/components/LabelProfilePicker.js +38 -0
- package/dist/features/print/components/labels.d.ts +117 -0
- package/dist/features/print/components/labels.js +258 -0
- package/dist/features/print/components/labels.style.css +46 -0
- package/dist/features/print/index.d.ts +6 -0
- package/dist/features/print/index.js +16 -0
- package/dist/features/products/columns/productTableColumns.js +5 -4
- package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +6 -6
- package/dist/features/products/components/PrizeDrawCollage.js +1 -1
- package/dist/features/products/components/PrizeDrawItemsEditor.js +1 -1
- package/dist/features/products/components/PrizeRevealModal.js +2 -2
- package/dist/features/products/components/ProductDetailPageView.js +18 -4
- package/dist/features/products/components/ProductForm.js +34 -23
- package/dist/features/products/components/ProductGrid.js +86 -62
- package/dist/features/products/constants/card-badges.d.ts +97 -0
- package/dist/features/products/constants/card-badges.js +100 -0
- package/dist/features/products/repository/products.repository.js +34 -1
- package/dist/features/products/schemas/firestore.d.ts +46 -3
- package/dist/features/products/schemas/firestore.js +21 -0
- package/dist/features/promotions/components/PromotionsView.js +1 -1
- package/dist/features/promotions/repository/claimed-coupons.repository.d.ts +32 -0
- package/dist/features/promotions/repository/claimed-coupons.repository.js +58 -0
- package/dist/features/promotions/schemas/firestore.js +30 -3
- package/dist/features/promotions/schemas/index.d.ts +6 -6
- package/dist/features/protection-claims/repository/protection-claims.repository.d.ts +54 -0
- package/dist/features/protection-claims/repository/protection-claims.repository.js +174 -0
- package/dist/features/protection-claims/schemas/firestore.d.ts +168 -0
- package/dist/features/protection-claims/schemas/firestore.js +130 -0
- package/dist/features/reviews/actions/review-actions.js +3 -2
- package/dist/features/reviews/components/ReviewModal.js +1 -1
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/reviews/schemas/firestore.d.ts +20 -1
- package/dist/features/scams/constants/scam-types.d.ts +2 -0
- package/dist/features/scams/constants/scam-types.js +18 -0
- package/dist/features/scams/schemas/report-form.d.ts +3 -3
- package/dist/features/scams/schemas/report-form.js +26 -1
- package/dist/features/search/components/Search.js +9 -9
- package/dist/features/search/components/SearchResultsClient.js +18 -3
- package/dist/features/search/components/SearchResultsPageView.d.ts +1 -6
- package/dist/features/search/components/SearchResultsPageView.js +2 -2
- package/dist/features/seller/actions/offer-actions.js +16 -1
- package/dist/features/seller/actions/seller-actions.js +14 -3
- package/dist/features/seller/components/CategoryInlineSelect.js +75 -11
- package/dist/features/seller/components/PrintCenterView.d.ts +5 -0
- package/dist/features/seller/components/PrintCenterView.js +41 -30
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutRequestView.js +16 -5
- package/dist/features/seller/components/SellerPayoutSettingsView.js +1 -1
- package/dist/features/seller/components/SellerProductShell.d.ts +16 -0
- package/dist/features/seller/components/SellerProductShell.js +123 -13
- package/dist/features/seller/components/SellerReviewsView.js +4 -2
- package/dist/features/seller/components/SellerSidebar.js +1 -1
- package/dist/features/seller/schemas/coupon-form.d.ts +26 -0
- package/dist/features/seller/schemas/coupon-form.js +27 -0
- package/dist/features/seller/schemas/product-form.d.ts +3 -0
- package/dist/features/seller/schemas/product-form.js +5 -0
- package/dist/features/shell/FormShell.js +2 -2
- package/dist/features/shell/QuickFormDrawer.js +14 -0
- package/dist/features/shell/SectionForm.d.ts +19 -0
- package/dist/features/shell/SectionForm.js +133 -9
- package/dist/features/shell/SectionForm.style.css +54 -0
- package/dist/features/shipments/components/AdminShipmentsView.js +16 -1
- package/dist/features/shipments/repository/shipment-items.repository.d.ts +9 -0
- package/dist/features/shipments/repository/shipment-items.repository.js +14 -0
- package/dist/features/site-settings/components/ActionPermissionsManager.js +1 -1
- package/dist/features/sticker-trace/components/StickerCommitPanel.js +1 -1
- package/dist/features/store-extensions/schemas/report-review-form.d.ts +8 -8
- package/dist/features/stores/components/StoreGuideHubView.js +1 -1
- package/dist/features/stores/components/StoreHeader.js +1 -1
- package/dist/features/support/schemas/firestore.d.ts +73 -2
- package/dist/features/support/schemas/firestore.js +59 -0
- package/dist/index.d.ts +16 -24
- package/dist/index.js +38 -47
- package/dist/next/ErrorBoundary.js +1 -1
- package/dist/next/routing/route-map.d.ts +24 -0
- package/dist/next/routing/route-map.js +40 -0
- package/dist/providers/payment-manual/index.d.ts +15 -1
- package/dist/providers/payment-manual/index.js +37 -0
- package/dist/providers/payment-phonepe/index.d.ts +14 -1
- package/dist/providers/payment-phonepe/index.js +36 -0
- package/dist/providers/payment-razorpay/index.d.ts +44 -1
- package/dist/providers/payment-razorpay/index.js +99 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +18 -0
- package/dist/providers/shipping-shiprocket/index.js +18 -0
- package/dist/schemas/registry.d.ts +44 -11
- package/dist/server-entry.d.ts +2 -0
- package/dist/server-entry.js +27 -0
- package/dist/server.d.ts +43 -0
- package/dist/server.js +98 -0
- package/dist/styles.css +418 -149
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +15 -12
- package/dist/tokens/themes/default-light.js +14 -11
- package/dist/tokens/tokens.css +106 -23
- package/dist/ui/DataTable.style.css +4 -4
- package/dist/ui/columns/cell-renderers.d.ts +20 -0
- package/dist/ui/columns/cell-renderers.js +26 -1
- package/dist/ui/columns/index.d.ts +1 -1
- package/dist/ui/columns/index.js +4 -1
- package/dist/ui/components/Badge.style.css +1 -1
- package/dist/ui/components/Breadcrumb.js +19 -1
- package/dist/ui/components/BulkActionBar.style.css +4 -4
- package/dist/ui/components/Button.style.css +1 -1
- package/dist/ui/components/Checkbox.style.css +1 -1
- package/dist/ui/components/FallbackShell.js +1 -1
- package/dist/ui/components/Form.d.ts +14 -1
- package/dist/ui/components/Form.js +2 -2
- package/dist/ui/components/FormField.js +18 -4
- package/dist/ui/components/FormField.style.css +43 -3
- package/dist/ui/components/GatedPrice.style.css +1 -1
- package/dist/ui/components/IconButton.style.css +1 -1
- package/dist/ui/components/Input.js +22 -1
- package/dist/ui/components/Input.style.css +38 -22
- package/dist/ui/components/ListingFilterDrawer.js +1 -1
- package/dist/ui/components/ListingToolbar.js +1 -1
- package/dist/ui/components/PaginatedSelect.js +0 -0
- package/dist/ui/components/Radio.style.css +1 -1
- package/dist/ui/components/Repeater.d.ts +53 -0
- package/dist/ui/components/Repeater.js +7 -0
- package/dist/ui/components/RichTextEditor.d.ts +20 -1
- package/dist/ui/components/RichTextEditor.js +23 -2
- package/dist/ui/components/Select.style.css +7 -21
- package/dist/ui/components/Semantic.js +27 -3
- package/dist/ui/components/TagInput.style.css +4 -9
- package/dist/ui/components/Textarea.style.css +4 -18
- package/dist/ui/components/Toggle.style.css +1 -1
- package/dist/ui/components/Typography.d.ts +3 -3
- package/dist/ui/components/Typography.js +15 -15
- package/dist/ui/components/ViewToggle.style.css +4 -4
- package/dist/ui/forms/AddAnotherToggle.d.ts +16 -0
- package/dist/ui/forms/AddAnotherToggle.js +56 -0
- package/dist/ui/forms/ColorPickerField.js +15 -2
- package/dist/ui/forms/FieldCheckbox.js +15 -2
- package/dist/ui/forms/FieldInput.d.ts +22 -1
- package/dist/ui/forms/FieldInput.js +19 -5
- package/dist/ui/forms/FieldLabel.d.ts +35 -0
- package/dist/ui/forms/FieldLabel.js +70 -0
- package/dist/ui/forms/FieldSelect.d.ts +4 -1
- package/dist/ui/forms/FieldSelect.js +27 -5
- package/dist/ui/forms/FieldTextarea.d.ts +4 -1
- package/dist/ui/forms/FieldTextarea.js +22 -5
- package/dist/ui/forms/FormShell.d.ts +17 -1
- package/dist/ui/forms/FormShell.js +36 -2
- package/dist/ui/forms/FormShell.style.css +41 -33
- package/dist/ui/forms/index.d.ts +5 -1
- package/dist/ui/forms/index.js +2 -0
- package/dist/ui/icons/icon-registry.d.ts +1 -0
- package/dist/ui/icons/icon-registry.js +17 -1
- package/dist/utils/id-generators.d.ts +80 -0
- package/dist/utils/id-generators.js +93 -0
- package/dist/utils/search-txt-builders.d.ts +12 -0
- package/dist/utils/search-txt-builders.js +17 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +106 -5
- package/dist/features/loyalty/api/admin/loyalty/grant/route.d.ts +0 -12
- package/dist/features/loyalty/api/admin/loyalty/grant/route.js +0 -38
- package/dist/features/loyalty/api/balance/route.d.ts +0 -12
- package/dist/features/loyalty/api/balance/route.js +0 -41
- package/dist/features/loyalty/api/earn/route.d.ts +0 -12
- package/dist/features/loyalty/api/earn/route.js +0 -38
- package/dist/features/loyalty/api/history/route.d.ts +0 -12
- package/dist/features/loyalty/api/history/route.js +0 -58
- package/dist/features/loyalty/api/redeem/route.d.ts +0 -12
- package/dist/features/loyalty/api/redeem/route.js +0 -38
- package/dist/features/loyalty/columns/index.d.ts +0 -17
- package/dist/features/loyalty/columns/index.js +0 -40
- package/dist/features/loyalty/components/CoinsDisplay.d.ts +0 -12
- package/dist/features/loyalty/components/CoinsDisplay.js +0 -10
- package/dist/features/loyalty/components/index.d.ts +0 -1
- package/dist/features/loyalty/components/index.js +0 -1
- package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +0 -4
- package/dist/features/loyalty/hooks/useLoyaltyBalance.js +0 -25
- package/dist/features/loyalty/index.d.ts +0 -6
- package/dist/features/loyalty/index.js +0 -6
- package/dist/features/loyalty/manifest.d.ts +0 -2
- package/dist/features/loyalty/manifest.js +0 -16
- package/dist/features/loyalty/messages/en.json +0 -19
- package/dist/features/loyalty/repository/loyalty.repository.d.ts +0 -8
- package/dist/features/loyalty/repository/loyalty.repository.js +0 -22
- package/dist/features/loyalty/schemas/index.d.ts +0 -85
- package/dist/features/loyalty/schemas/index.js +0 -40
- package/dist/features/loyalty/server.d.ts +0 -6
- package/dist/features/loyalty/server.js +0 -6
- package/dist/features/loyalty/types/index.d.ts +0 -31
- package/dist/features/loyalty/types/index.js +0 -1
- package/dist/features/loyalty/types/loyalty-config.d.ts +0 -7
- package/dist/features/loyalty/types/loyalty-config.js +0 -1
- package/dist/features/loyalty/types/loyalty-math.d.ts +0 -9
- package/dist/features/loyalty/types/loyalty-math.js +0 -27
- package/dist/features/products/components/ProductOwnerQuickActions.d.ts +0 -11
- package/dist/features/products/components/ProductOwnerQuickActions.js +0 -120
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import Link from "next/link.js";
|
|
4
4
|
import { usePathname } from "next/navigation.js";
|
|
5
|
+
import { LISTING_TYPE_REGISTRY } from "../../_internal/shared/listing-types/_registry.js";
|
|
5
6
|
import { Div, Li, Nav, Ol, Span } from "../../ui/index.js";
|
|
6
7
|
/** Map of path segments → human-readable labels. */
|
|
7
8
|
const DEFAULT_PATH_LABELS = {
|
|
@@ -28,6 +29,36 @@ const DEFAULT_PATH_LABELS = {
|
|
|
28
29
|
view: "View",
|
|
29
30
|
add: "Add",
|
|
30
31
|
edit: "Edit",
|
|
32
|
+
/*
|
|
33
|
+
* Real public route segments whose title-cased form is wrong or ugly.
|
|
34
|
+
* Anything absent here still renders — `capitalize()` title-cases every
|
|
35
|
+
* word, so `digital-codes` reads "Digital Codes" unaided. These are only the
|
|
36
|
+
* ones where casing alone does not get there (`faqs` -> "Faqs",
|
|
37
|
+
* `pre-orders` -> "Pre Orders").
|
|
38
|
+
*/
|
|
39
|
+
faqs: "FAQs",
|
|
40
|
+
"pre-orders": "Pre-Orders",
|
|
41
|
+
"prize-draws": "Prize Draws",
|
|
42
|
+
"digital-codes": "Digital Codes",
|
|
43
|
+
beys: "Beyblades",
|
|
44
|
+
parts: "Parts",
|
|
45
|
+
brands: "Brands",
|
|
46
|
+
franchise: "Franchise",
|
|
47
|
+
bundles: "Bundles",
|
|
48
|
+
stores: "Stores",
|
|
49
|
+
sellers: "Sellers",
|
|
50
|
+
events: "Events",
|
|
51
|
+
reviews: "Reviews",
|
|
52
|
+
auctions: "Auctions",
|
|
53
|
+
promotions: "Promotions",
|
|
54
|
+
classified: "Classified",
|
|
55
|
+
live: "Live Items",
|
|
56
|
+
art: "Art",
|
|
57
|
+
stickers: "Stickers",
|
|
58
|
+
catalogue: "Catalogue",
|
|
59
|
+
credits: "Credits",
|
|
60
|
+
about: "About",
|
|
61
|
+
contact: "Contact",
|
|
31
62
|
};
|
|
32
63
|
// Common locale codes filtered out of path segments
|
|
33
64
|
const LOCALE_CODES = new Set([
|
|
@@ -51,8 +82,89 @@ const LOCALE_CODES = new Set([
|
|
|
51
82
|
"pa",
|
|
52
83
|
"ur",
|
|
53
84
|
]);
|
|
85
|
+
/*
|
|
86
|
+
* ── 🛑 THE LAST SEGMENT OF A DETAIL ROUTE IS DATA, NOT A LABEL ─────────────
|
|
87
|
+
*
|
|
88
|
+
* This component only sees `usePathname()`, so it cannot know which segments
|
|
89
|
+
* are dynamic. Title-casing one anyway produced, verbatim in production:
|
|
90
|
+
*
|
|
91
|
+
* Home / Products / Product beyblade x xtreme stadium bx 10
|
|
92
|
+
*
|
|
93
|
+
* while the page's OWN breadcrumb, rendered directly beneath it, correctly
|
|
94
|
+
* read `Xtreme Stadiums › Beyblade X Xtreme Stadium (BX-10)`. Only the page
|
|
95
|
+
* holds the real title; a pathname cannot be turned into one.
|
|
96
|
+
*
|
|
97
|
+
* So an entity id is OMITTED rather than guessed at — the breadcrumb simply
|
|
98
|
+
* ends at `Home / Products`, which is true, useful and navigable.
|
|
99
|
+
*
|
|
100
|
+
* 🛑 CORRECTED 2026-10-21 — this read "Every detail page in this app renders
|
|
101
|
+
* its own trail with real titles, which is why dropping the crumb loses
|
|
102
|
+
* nothing", and that is FALSE. Measured across five detail views: only
|
|
103
|
+
* `ProductDetailPageView` renders one. `AuctionDetailPageView`,
|
|
104
|
+
* `StoreDetailLayoutView`, `BlogPostView` and `BrandDetailPageView` render
|
|
105
|
+
* NONE, so on those four the shortened trail above is the only breadcrumb
|
|
106
|
+
* there is.
|
|
107
|
+
*
|
|
108
|
+
* That does not change the decision — a trail ending at `Home / Auctions` is
|
|
109
|
+
* still correct, and title-casing an id produced
|
|
110
|
+
* `Product beyblade x xtreme stadium bx 10`, which was not. But the
|
|
111
|
+
* justification matters, because the false version invites the obvious next
|
|
112
|
+
* move: "detail pages have their own trail, so suppress this component on
|
|
113
|
+
* detail routes entirely". That would strip the breadcrumb from those four
|
|
114
|
+
* surfaces. The duplicate is handled by `:has()` in
|
|
115
|
+
* `AutoBreadcrumbs.style.css`, which fires only where a page actually
|
|
116
|
+
* renders its own.
|
|
117
|
+
*
|
|
118
|
+
* 🛑 The listing prefixes are READ FROM `LISTING_TYPE_REGISTRY`, never
|
|
119
|
+
* re-listed here. Two enumerations of one union always drift (Root Cause #42 /
|
|
120
|
+
* #61), and that registry is already the single source for all nine listing
|
|
121
|
+
* types' `slugPrefix`.
|
|
122
|
+
*
|
|
123
|
+
* The non-listing prefixes below cannot come from there because no registry
|
|
124
|
+
* covers them; they are the documented slug-prefix system in CLAUDE.md, and
|
|
125
|
+
* only the ones that actually appear in a PUBLIC url are listed — an
|
|
126
|
+
* `order-`/`payout-`/`notif-` id never reaches a public breadcrumb.
|
|
127
|
+
*
|
|
128
|
+
* 🛑 This does NOT catch a prefix-less slug: `/beys/variares-d-d` still renders
|
|
129
|
+
* "Variares D D". That is a known, accepted limitation rather than an
|
|
130
|
+
* oversight — it is readable, it is not an id-shaped string, and the bey page's
|
|
131
|
+
* own breadcrumb carries the proper name. Fixing it properly means the page
|
|
132
|
+
* supplying its leaf label, which is plumbing this component cannot do alone.
|
|
133
|
+
*/
|
|
134
|
+
const NON_LISTING_PUBLIC_PREFIXES = [
|
|
135
|
+
"category-",
|
|
136
|
+
"brand-",
|
|
137
|
+
"store-",
|
|
138
|
+
"blog-",
|
|
139
|
+
"event-",
|
|
140
|
+
"review-",
|
|
141
|
+
"faq-",
|
|
142
|
+
"coupon-",
|
|
143
|
+
"group-",
|
|
144
|
+
"sublisting-",
|
|
145
|
+
"user-",
|
|
146
|
+
"mycatalog-",
|
|
147
|
+
"catalog-",
|
|
148
|
+
"scammer-",
|
|
149
|
+
];
|
|
150
|
+
function isOpaqueEntityId(seg) {
|
|
151
|
+
const listingPrefixes = Object.values(LISTING_TYPE_REGISTRY)
|
|
152
|
+
.map((p) => p.slugPrefix)
|
|
153
|
+
.filter((p) => Boolean(p));
|
|
154
|
+
return [...listingPrefixes, ...NON_LISTING_PUBLIC_PREFIXES].some((p) => seg.startsWith(p));
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Title-case a hyphenated path segment — EVERY word, not just the first.
|
|
158
|
+
*
|
|
159
|
+
* The previous implementation uppercased only `charAt(0)`, so a multi-word
|
|
160
|
+
* segment came out as sentence-case mush ("Pre orders", "Digital codes").
|
|
161
|
+
*/
|
|
54
162
|
function capitalize(s) {
|
|
55
|
-
return s
|
|
163
|
+
return s
|
|
164
|
+
.split("-")
|
|
165
|
+
.filter(Boolean)
|
|
166
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
167
|
+
.join(" ");
|
|
56
168
|
}
|
|
57
169
|
/**
|
|
58
170
|
* AutoBreadcrumbs — generates breadcrumb navigation automatically from the
|
|
@@ -69,15 +181,62 @@ export function AutoBreadcrumbs({ pathLabels, separator = "/", className = "", r
|
|
|
69
181
|
const localePrefix = hasLocalePrefix ? `/${rawSegments[0]}` : "";
|
|
70
182
|
const segments = rawSegments.filter((seg) => !LOCALE_CODES.has(seg.toLowerCase()) &&
|
|
71
183
|
!/^[0-9a-f-]{8,}$/.test(seg) &&
|
|
72
|
-
!/^\d+$/.test(seg)
|
|
184
|
+
!/^\d+$/.test(seg) &&
|
|
185
|
+
/* An entity id carries no label a pathname can recover — see above. */
|
|
186
|
+
!isOpaqueEntityId(seg));
|
|
73
187
|
if (segments.length === 0)
|
|
74
188
|
return null;
|
|
189
|
+
/*
|
|
190
|
+
* 🛑 NOT RENDERED INSIDE A DASHBOARD, and the argument is redundancy rather
|
|
191
|
+
* than taste.
|
|
192
|
+
*
|
|
193
|
+
* On `/admin/products` this band reads "Home / Admin / Products" directly
|
|
194
|
+
* above an `<h1>Products</h1>` — which `DataListingView` and `FormShell`
|
|
195
|
+
* both render now — while the sidebar has that group open and its link
|
|
196
|
+
* marked via `activePath`. Three statements of the same position, in a
|
|
197
|
+
* ~38px strip that is NOT sticky, so it scrolls away and contributes
|
|
198
|
+
* nothing after the first screen. It is pure fold cost: measured, the
|
|
199
|
+
* dashboard chrome ran to ~243px before the first row of content.
|
|
200
|
+
*
|
|
201
|
+
* 🛑 The suppression is keyed on being INSIDE A DASHBOARD, never on "is a
|
|
202
|
+
* detail route". A previous version of this file claimed every detail page
|
|
203
|
+
* renders its own trail; measured, only 1 of 5 does — auction, store, blog
|
|
204
|
+
* and brand render none, so a detail-route rule would have stripped the
|
|
205
|
+
* breadcrumb from four public pages that have nothing else. A dashboard has
|
|
206
|
+
* a sidebar and an h1; a public detail page has neither.
|
|
207
|
+
*
|
|
208
|
+
* The regex matches the LOCALE-STRIPPED segments, so it is unaffected by
|
|
209
|
+
* whether a `/en` prefix is present.
|
|
210
|
+
*/
|
|
211
|
+
const isDashboard = ["admin", "store", "user"].includes(segments[0]?.toLowerCase() ?? "");
|
|
212
|
+
if (isDashboard)
|
|
213
|
+
return null;
|
|
75
214
|
const crumbs = segments.map((seg, i) => ({
|
|
76
215
|
label: labels[seg] ?? capitalize(seg),
|
|
77
216
|
href: `${localePrefix}/${segments.slice(0, i + 1).join("/")}`,
|
|
78
217
|
}));
|
|
79
218
|
const allCrumbs = [{ label: "Home", href: localePrefix || "/" }, ...crumbs];
|
|
80
|
-
|
|
219
|
+
/*
|
|
220
|
+
* 🛑 The `/80` that used to sit in the root className was NOT leading,
|
|
221
|
+
* which is why the hand-sweep that fixed the other 28 missed it and
|
|
222
|
+
* `audit-dead-css-classes` caught it: the regexes assumed
|
|
223
|
+
* `className="/80 …"`, and this was `className="border-y /80 …"`.
|
|
224
|
+
*
|
|
225
|
+
* It is the same codemod residue — a stripped `bg-white/80` leaving its
|
|
226
|
+
* modifier — and the same silent no-op. Dropped rather than restored: the
|
|
227
|
+
* element already takes `surface="default"`, so the translucency it was
|
|
228
|
+
* reaching for belongs in that token, and the two `supports-[…]` rules
|
|
229
|
+
* beside it already handle the backdrop-filter case with their own alphas.
|
|
230
|
+
*
|
|
231
|
+
* 🛑 AND THIS COMMENT LIVES HERE, ABOVE `return`, FOR A REASON. It was
|
|
232
|
+
* written as a `{/* … *␣/}` block between `return (` and the root element —
|
|
233
|
+
* i.e. in EXPRESSION position, where JSX comment syntax is not valid. That
|
|
234
|
+
* does not parse, and it took the whole appkit build down (TS1005 ×3,
|
|
235
|
+
* TS1128, TS1109). A brace-balance check passed it, because `{/* … *␣/}` is
|
|
236
|
+
* brace-balanced; only `tsc` sees it. Never open a JSX comment before the
|
|
237
|
+
* first element.
|
|
238
|
+
*/
|
|
239
|
+
return (_jsx(Div, { border: "default", className: "appkit-auto-breadcrumbs border-y backdrop-blur supports-[backdrop-filter]:bg-white/90 dark:supports-[backdrop-filter]:bg-slate-950/85", surface: "default", children: _jsx(Div, { className: "container mx-auto max-w-[1920px] px-[var(--appkit-space-5)] sm:px-[var(--appkit-space-6)] lg:px-[var(--appkit-space-8)]", padding: "y-xs", children: _jsx(Nav, { "aria-label": "Breadcrumb", className: className, children: _jsx(Ol, { className: "flex items-center gap-[var(--appkit-space-2)] flex-wrap", size: "sm", children: allCrumbs.map((crumb, index) => {
|
|
81
240
|
const isLast = index === allCrumbs.length - 1;
|
|
82
241
|
return (_jsxs(Li, { layout: "flex-center", gap: "2", children: [isLast ? (_jsx(Span, { "aria-current": "page", color: "primary", children: crumb.label })) : renderLink ? (renderLink(crumb.href, crumb.label)) : (_jsx(Link, { href: crumb.href, className: "text-[var(--appkit-color-text-muted)] hover:text-zinc-950 dark:hover:text-white transition-colors", children: crumb.label })), !isLast && (_jsx(Span, { className: "text-[var(--appkit-color-text-muted)]/90 select-none", color: "muted", "aria-hidden": "true", children: separator }))] }, crumb.href));
|
|
83
242
|
}) }) }) }) }));
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* One breadcrumb per page.
|
|
3
|
+
*
|
|
4
|
+
* `AppLayoutShell` renders `<AutoBreadcrumbs>` on every route, derived from
|
|
5
|
+
* `usePathname()`. Some pages ALSO render their own trail with real entity
|
|
6
|
+
* titles — `ProductDetailPageView`, `CategoryDetailPageView`, the scam
|
|
7
|
+
* registry — and those pages showed two breadcrumbs stacked. `AutoBreadcrumbs`'
|
|
8
|
+
* own header records seeing exactly that in production:
|
|
9
|
+
*
|
|
10
|
+
* Home / Products / Product beyblade x xtreme stadium bx 10
|
|
11
|
+
* Xtreme Stadiums › Beyblade X Xtreme Stadium (BX-10)
|
|
12
|
+
*
|
|
13
|
+
* and responded by shortening the top one rather than hiding it.
|
|
14
|
+
*
|
|
15
|
+
* ── 🛑 WHY CSS AND NOT REACT ────────────────────────────────────────────────
|
|
16
|
+
*
|
|
17
|
+
* A child cannot hide an already-rendered ancestor's sibling. The shell
|
|
18
|
+
* renders `<AutoBreadcrumbs>` BEFORE `{children}`, so a context or a state
|
|
19
|
+
* flag the page sets arrives a frame late — and hiding a full-width strip one
|
|
20
|
+
* frame after paint is a layout shift at the top of the document, which is the
|
|
21
|
+
* exact defect just fixed on the announcement bar (CLS 0.822). The fix cannot
|
|
22
|
+
* be allowed to become the same bug.
|
|
23
|
+
*
|
|
24
|
+
* `:has()` resolves it during the first style pass: no state, no effect, no
|
|
25
|
+
* frame where both are visible.
|
|
26
|
+
*
|
|
27
|
+
* 🛑 AND IT DEGRADES SAFELY. Where `:has()` is unsupported the rule simply
|
|
28
|
+
* does not match and both breadcrumbs render — today's behaviour. That is the
|
|
29
|
+
* right direction for a progressive enhancement: the failure mode is
|
|
30
|
+
* redundancy, never a missing breadcrumb.
|
|
31
|
+
*
|
|
32
|
+
* 🛑 SCOPED TO THE AUTOMATIC ONE. The page's trail is the one with real
|
|
33
|
+
* titles, so the generic one yields. Suppressing by ROUTE instead would have
|
|
34
|
+
* been wrong: only one of five detail views measured actually renders its own
|
|
35
|
+
* trail, so a route-shaped rule would strip the breadcrumb entirely from
|
|
36
|
+
* auction, store, blog and brand pages — see the correction in
|
|
37
|
+
* `AutoBreadcrumbs.tsx`'s header.
|
|
38
|
+
*
|
|
39
|
+
* @tag domain:layout
|
|
40
|
+
* @tag layer:feature
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
body:has(.appkit-page-breadcrumb) .appkit-auto-breadcrumbs {
|
|
44
|
+
display: none;
|
|
45
|
+
}
|
|
@@ -72,7 +72,7 @@ export interface BottomNavbarProps {
|
|
|
72
72
|
onMoreToggle?: () => void;
|
|
73
73
|
/** CSS class applied to the active nav item. Default: "text-primary-600 dark:text-primary-400" */
|
|
74
74
|
activeClassName?: string;
|
|
75
|
-
/** CSS class applied to inactive nav items. Default: "text-[var(--appkit-color-text-muted)]
|
|
75
|
+
/** CSS class applied to inactive nav items. Default: "text-[var(--appkit-color-text-muted)]" */
|
|
76
76
|
inactiveClassName?: string;
|
|
77
77
|
/** CSS class applied to nav icons */
|
|
78
78
|
iconClassName?: string;
|
|
@@ -45,7 +45,7 @@ function BottomNavSlot({ item, isActive, onOpenChildren, activeClassName, inacti
|
|
|
45
45
|
*
|
|
46
46
|
* Pass `user` from your auth context to render the profile slot with avatar.
|
|
47
47
|
*/
|
|
48
|
-
export function BottomNavbar({ user, userId, homeHref, shopHref, cartHref, wishlistHref, profileHref, loginHref, onSearchToggle, navItems, onMoreToggle, activeClassName = "text-primary-600 dark:text-primary-400", inactiveClassName = "text-[var(--appkit-color-text-muted)]
|
|
48
|
+
export function BottomNavbar({ user, userId, homeHref, shopHref, cartHref, wishlistHref, profileHref, loginHref, onSearchToggle, navItems, onMoreToggle, activeClassName = "text-primary-600 dark:text-primary-400", inactiveClassName = "text-[var(--appkit-color-text-muted)]", iconClassName, labelClassName = "text-[11px] leading-tight font-medium", getRoleBadgeClass, }) {
|
|
49
49
|
const pathname = usePathname();
|
|
50
50
|
const wishlistCount = useWishlistCount(userId);
|
|
51
51
|
const cartCount = useCartCount(!!userId);
|
|
@@ -90,5 +90,5 @@ export function BottomNavbar({ user, userId, homeHref, shopHref, cartHref, wishl
|
|
|
90
90
|
return (_jsxs(_Fragment, { children: [_jsxs(BottomNavLayout, { ariaLabel: labels.mobileNav, children: [visibleItems.map((item) => (_jsx(Li, { className: "flex-1", children: _jsx(BottomNavSlot, { item: item, isActive: isSlotActive(item), onOpenChildren: (it) => setOpenKey(it.key), activeClassName: activeClassName, inactiveClassName: inactiveClassName, iconClassName: iconClassName, labelClassName: labelClassName, fallbackIcon: defaultIcon }) }, item.key))), cartHref && (_jsx(Li, { className: "flex-1", children: _jsxs(TextLink, { href: cartHref, variant: "none", className: `${slotClassName} ${pathname === cartHref ? activeClassName : inactiveClassName}`, "aria-label": cartCount > 0 ? `${labels.cart}, ${cartCount} items` : labels.cart, children: [_jsxs(Span, { className: "relative", children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 shrink-0", 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" }) }), cartCount > 0 && (_jsx(Span, { size: "xs", weight: "semibold", className: CLS_COUNT_BADGE, children: cartCount > 9 ? "9+" : cartCount }))] }), _jsx(Span, { className: labelClassName, children: labels.cart })] }) })), _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 shrink-0", 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 })] }) })] }), _jsx(Drawer, { isOpen: !!openItem, onClose: () => setOpenKey(null), title: openItem?.label, side: "bottom", children: _jsxs(Ul, { className: "list-none", children: [openItem && (_jsx(Li, { children: _jsx(TextLink, { href: openItem.href, variant: "none", className: "block rounded-md px-[var(--appkit-space-3)] py-[var(--appkit-space-3)] text-[length:var(--appkit-text-sm)] font-medium text-[var(--appkit-color-text)]", children: openItem.label }) })), (openItem?.children ?? []).map((child) => (_jsx(Li, { children: _jsxs(TextLink, { href: child.href, variant: "none", className: "flex items-start gap-[var(--appkit-space-2)] rounded-md px-[var(--appkit-space-3)] py-[var(--appkit-space-3)] text-[length:var(--appkit-text-sm)] text-[var(--appkit-color-text)]", children: [child.icon && (_jsx(Span, { className: "flex-shrink-0 mt-[var(--appkit-space-0-5)]", "aria-hidden": "true", children: child.icon })), _jsxs(Span, { className: "block", children: [_jsx(Span, { weight: "medium", className: "block", children: child.label }), child.description && (_jsx(Span, { size: "xs", color: "muted", className: "block mt-[var(--appkit-space-0-5)] whitespace-normal", children: child.description }))] })] }) }, child.href)))] }) })] }));
|
|
91
91
|
}
|
|
92
92
|
return (_jsxs(BottomNavLayout, { ariaLabel: labels.mobileNav, children: [_jsx(Li, { className: "flex-1", 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", 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", 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 shrink-0", 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", children: _jsxs(TextLink, { href: cartHref, variant: "none", className: `${slotClassName} ${pathname === cartHref ? activeClassName : inactiveClassName}`, "aria-label": cartCount > 0 ? `${labels.cart}, ${cartCount} items` : labels.cart, children: [_jsxs(Span, { className: "relative", children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 shrink-0", 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" }) }), cartCount > 0 && (_jsx(Span, { size: "xs", weight: "semibold", className: CLS_COUNT_BADGE, children: cartCount > 9 ? "9+" : cartCount }))] }), _jsx(Span, { className: labelClassName, children: labels.cart })] }) }), wishlistHref && (_jsx(Li, { className: "flex-1", children: _jsxs(TextLink, { href: wishlistHref, variant: "none", className: `${slotClassName} ${pathname === wishlistHref ? activeClassName : inactiveClassName}`, "aria-label": wishlistCount > 0 ? `${labels.wishlist}, ${wishlistCount} items` : labels.wishlist, children: [_jsxs(Span, { className: "relative", children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", 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, { size: "xs", weight: "semibold", className: CLS_COUNT_BADGE, children: wishlistCount > 9 ? "9+" : wishlistCount }))] }), _jsx(Span, { className: labelClassName, children: labels.wishlist })] }) })), _jsx(Li, { className: "flex-1", children: user ? (_jsxs(TextLink, { href: profileHref, variant: "none", className: `${slotClassName} ${pathname === profileHref ? activeClassName : inactiveClassName}`, "aria-label": labels.profile, children: [_jsx(AvatarDisplay, { cropData: user.avatarMetadata ||
|
|
93
|
-
(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] uppercase leading-none ${getRoleBadgeClass ? getRoleBadgeClass(user.role) : "text-[var(--appkit-color-text-muted)]
|
|
93
|
+
(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] uppercase leading-none ${getRoleBadgeClass ? getRoleBadgeClass(user.role) : "text-[var(--appkit-color-text-muted)]"}`, weight: "semibold", 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 })) })] }));
|
|
94
94
|
}
|
|
@@ -8,6 +8,6 @@ const sizeClasses = {
|
|
|
8
8
|
xl: "w-20 h-20",
|
|
9
9
|
};
|
|
10
10
|
export function MediaAvatar({ src, alt, size = "md", className = "", }) {
|
|
11
|
-
return (_jsx(Div, { className: `relative ${sizeClasses[size]} overflow-hidden flex-shrink-0 ${className}`, rounded: "full", children: _jsx(MediaImage, { src: src, alt: alt, size: "avatar", objectFit: "cover" }) }));
|
|
11
|
+
return (_jsx(Div, { className: `relative ${sizeClasses[size]} overflow-hidden flex-shrink-0 ${className}`, rounded: "full", children: _jsx(MediaImage, { src: src, alt: alt, size: "avatar", objectFit: "cover", fill: true }) }));
|
|
12
12
|
}
|
|
13
13
|
export default MediaAvatar;
|
|
@@ -38,11 +38,31 @@ export interface MediaImageProps {
|
|
|
38
38
|
*
|
|
39
39
|
* Pass `'cover'` explicitly where a FILLED box is the component's contract
|
|
40
40
|
* rather than a preference — a full-bleed backdrop with text over it, or a
|
|
41
|
-
* circular avatar.
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* circular avatar. A letterboxed backdrop would put the dim overlay and the
|
|
42
|
+
* headline on bare surface.
|
|
43
|
+
*
|
|
44
|
+
* 🛑 Counted 2026-10-21: **six** call sites, not the three this said —
|
|
45
|
+
* `MediaAvatar`, both `HeroCarousel` backgrounds, `CTABannerSection`,
|
|
46
|
+
* `CustomCardsSection` and `PublicCatalogueItemDetailView`'s thumbnail
|
|
47
|
+
* strip. Four of them also pass `fill`; the two that do not sit in parents
|
|
48
|
+
* whose shape already matches the size's own box.
|
|
44
49
|
*/
|
|
45
50
|
objectFit?: "cover" | "contain";
|
|
51
|
+
/**
|
|
52
|
+
* Fill the parent's box instead of establishing one from `size`.
|
|
53
|
+
*
|
|
54
|
+
* 🛑 Only for a parent that ALREADY has a definite height — a full-bleed
|
|
55
|
+
* backdrop, a fixed-size avatar circle, a carousel slide. In an auto-height
|
|
56
|
+
* parent this reproduces the exact bug `SIZE_BOX` exists to fix: the image
|
|
57
|
+
* collapses to zero and renders as empty space.
|
|
58
|
+
*
|
|
59
|
+
* The call sites that need it are close to the ones already passing
|
|
60
|
+
* `objectFit="cover"` — a filled box and a cropped fit are usually the same
|
|
61
|
+
* contract stated twice — but the two are NOT the same decision, so they are
|
|
62
|
+
* separate props. `cover` says how to fit; `fill` says where the box comes
|
|
63
|
+
* from.
|
|
64
|
+
*/
|
|
65
|
+
fill?: boolean;
|
|
46
66
|
/**
|
|
47
67
|
* Emoji or text to show when `src` is undefined.
|
|
48
68
|
* Falls back to the per-size default icon.
|
|
@@ -92,5 +112,5 @@ export interface MediaImageProps {
|
|
|
92
112
|
media?: string;
|
|
93
113
|
}>;
|
|
94
114
|
}
|
|
95
|
-
export declare function MediaImage({ src, alt, size, priority, loading, fetchPriority, objectFit, fallback, className, rounded, shadow, style, sources, onError, }: MediaImageProps): import("react").JSX.Element;
|
|
115
|
+
export declare function MediaImage({ src, alt, size, priority, loading, fetchPriority, objectFit, fallback, className, rounded, shadow, style, sources, onError, fill, }: MediaImageProps): import("react").JSX.Element;
|
|
96
116
|
export default MediaImage;
|
|
@@ -19,6 +19,38 @@ const SIZE_HINTS = {
|
|
|
19
19
|
gallery: "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw",
|
|
20
20
|
avatar: "(max-width: 640px) 48px, 56px",
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* The BOX each size establishes on the wrapper.
|
|
24
|
+
*
|
|
25
|
+
* 🛑 THIS IS THE FIX FOR A DEFECT THAT MADE `size` A LIE. Until 2026-10-21 the
|
|
26
|
+
* `size` prop fed exactly two things — `SIZE_HINTS` (the `sizes` download
|
|
27
|
+
* attribute) and `FALLBACK_ICONS` (which emoji) — and **neither affected
|
|
28
|
+
* layout**. Every render branch was `relative w-full h-full` around an
|
|
29
|
+
* `<Image fill>`, so the component had an unstated contract: the PARENT must
|
|
30
|
+
* supply a definite height. `h-full` against an auto-height parent is 0, and a
|
|
31
|
+
* `fill` child is absolutely positioned and contributes none of its own, so
|
|
32
|
+
* the whole thing collapsed to zero and rendered as blank space.
|
|
33
|
+
*
|
|
34
|
+
* `size="hero"` therefore read as "this is hero-shaped" and produced **zero
|
|
35
|
+
* pixels**. `ProductGrid` worked only because its own call site wraps the
|
|
36
|
+
* image in `aspect-square` — so `card` was correct BY ACCIDENT OF WHERE IT WAS
|
|
37
|
+
* USED, which is why the reported symptom was "anything which is not a card".
|
|
38
|
+
*
|
|
39
|
+
* Same mechanism as Root Cause #68, one component over, and fixed the same
|
|
40
|
+
* way: at the primitive, not at ~100 call sites. A `Record<MediaImageSize, …>`
|
|
41
|
+
* means a seventh size cannot be added without declaring its shape.
|
|
42
|
+
*
|
|
43
|
+
* Call sites that must genuinely fill a parent they have already sized pass
|
|
44
|
+
* `fill` — see that prop.
|
|
45
|
+
*/
|
|
46
|
+
const SIZE_BOX = {
|
|
47
|
+
thumbnail: "aspect-square",
|
|
48
|
+
card: "aspect-square",
|
|
49
|
+
gallery: "aspect-square",
|
|
50
|
+
avatar: "aspect-square",
|
|
51
|
+
hero: "aspect-video",
|
|
52
|
+
banner: "aspect-[3/1]",
|
|
53
|
+
};
|
|
22
54
|
const FALLBACK_ICONS = {
|
|
23
55
|
thumbnail: "📦",
|
|
24
56
|
card: "📦",
|
|
@@ -67,7 +99,7 @@ function resolveSrcSet(input) {
|
|
|
67
99
|
.filter(Boolean)
|
|
68
100
|
.join(", ");
|
|
69
101
|
}
|
|
70
|
-
export function MediaImage({ src, alt, size = "card", priority = false, loading, fetchPriority, objectFit = "contain", fallback, className, rounded, shadow, style, sources, onError, }) {
|
|
102
|
+
export function MediaImage({ src, alt, size = "card", priority = false, loading, fetchPriority, objectFit = "contain", fallback, className, rounded, shadow, style, sources, onError, fill = false, }) {
|
|
71
103
|
const [hasError, setHasError] = useState(false);
|
|
72
104
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
73
105
|
const [retryCount, setRetryCount] = useState(0);
|
|
@@ -75,6 +107,14 @@ export function MediaImage({ src, alt, size = "card", priority = false, loading,
|
|
|
75
107
|
const icon = fallback ?? FALLBACK_ICONS[size];
|
|
76
108
|
const fitClass = objectFit === "contain" ? "object-contain" : "object-cover";
|
|
77
109
|
const resolvedSrc = resolveMediaUrl(src);
|
|
110
|
+
/*
|
|
111
|
+
* The wrapper's box: the size's own shape by default, the parent's when the
|
|
112
|
+
* caller opts in with `fill`. Shared by all three render branches below so
|
|
113
|
+
* the placeholder, the `<picture>` and the plain `<Image>` cannot disagree
|
|
114
|
+
* about their dimensions — a fallback that occupies a different box from the
|
|
115
|
+
* image it replaces makes a grid jump as things load.
|
|
116
|
+
*/
|
|
117
|
+
const boxClass = fill ? "h-full" : SIZE_BOX[size];
|
|
78
118
|
// Reset error/load/retry state whenever the resolved src actually changes.
|
|
79
119
|
// Without this, a component instance that hit a load failure once (e.g.
|
|
80
120
|
// lost the post-upload propagation race above) latches hasError forever,
|
|
@@ -106,7 +146,7 @@ export function MediaImage({ src, alt, size = "card", priority = false, loading,
|
|
|
106
146
|
onError?.();
|
|
107
147
|
};
|
|
108
148
|
if (!resolvedSrc || hasError) {
|
|
109
|
-
return (_jsx(Row, { className: `relative w-full
|
|
149
|
+
return (_jsx(Row, { className: `relative w-full ${boxClass} overflow-hidden text-zinc-400 text-[length:var(--appkit-text-4xl)]${wrapperExtra ? ` ${wrapperExtra}` : ""}`, align: "center", justify: "center", surface: "subtle", role: "img", "aria-label": alt, children: _jsx(Span, { "aria-hidden": "true", children: icon }) }));
|
|
110
150
|
}
|
|
111
151
|
const isSvg = resolvedSrc.toLowerCase().endsWith(".svg") ||
|
|
112
152
|
resolvedSrc.includes("image/svg") ||
|
|
@@ -123,11 +163,11 @@ export function MediaImage({ src, alt, size = "card", priority = false, loading,
|
|
|
123
163
|
// browser must pick the matching `<source>` itself. Loading + decoding hints
|
|
124
164
|
// come from the consumer's preset.
|
|
125
165
|
if (sources && sources.length > 0) {
|
|
126
|
-
return (_jsxs(Div, { className: `relative w-full
|
|
166
|
+
return (_jsxs(Div, { className: `relative w-full ${boxClass} overflow-hidden${wrapperExtra ? ` ${wrapperExtra}` : ""}`, style: style, children: [!isLoaded && (_jsx(Div, { className: "absolute inset-0 animate-pulse", surface: "subtle", "aria-hidden": "true" })), _jsxs("picture", { children: [sources.map((source, index) => (_jsx("source", { srcSet: resolveSrcSet(source.srcSet), type: source.type, media: source.media }, `${source.media ?? ""}-${source.type ?? ""}-${index}`))), _jsx("img", { src: requestSrc, alt: alt, loading: loading ?? (priority ? "eager" : "lazy"), fetchPriority: resolvedFetchPriority, decoding: "async",
|
|
127
167
|
// catalogued primitive for media (variant catalogue allows the inner
|
|
128
168
|
// <img> here). Object-fit + className come from typed props.
|
|
129
169
|
className: `absolute inset-0 w-full h-full ${fitClass}`, onLoad: () => setIsLoaded(true), onError: handleError })] })] }));
|
|
130
170
|
}
|
|
131
|
-
return (_jsxs(Div, { className: `relative w-full
|
|
171
|
+
return (_jsxs(Div, { className: `relative w-full ${boxClass} overflow-hidden${wrapperExtra ? ` ${wrapperExtra}` : ""}`, style: style, children: [!isLoaded && (_jsx(Div, { className: "absolute inset-0 animate-pulse", surface: "subtle", "aria-hidden": "true" })), _jsx(Image, { src: requestSrc, alt: alt, fill: true, priority: priority, fetchPriority: resolvedFetchPriority, loading: loading ?? (priority ? "eager" : "lazy"), className: fitClass, sizes: SIZE_HINTS[size], onLoad: () => setIsLoaded(true), onError: handleError, unoptimized: isSvg })] }));
|
|
132
172
|
}
|
|
133
173
|
export default MediaImage;
|
|
@@ -31,7 +31,7 @@ function IconBtn({ onClick, disabled, ariaLabel, ariaCurrent, className, childre
|
|
|
31
31
|
}
|
|
32
32
|
// --- Controls bar sub-components ---------------------------------------------
|
|
33
33
|
function LightboxControlsBar({ items, index, zoom, isFullscreen, L, goPrev, goNext, zoomIn, zoomOut, resetZoom, toggleFullscreen, onClose, }) {
|
|
34
|
-
return (_jsxs(Row, { gap: "xs", className: "bg-black/85 backdrop-blur-sm shrink-0 border-t border-white/10", padding: "inline", align: "center", justify: "center", wrap: true, children: [items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goPrev(); }, ariaLabel: L.prevImage, children: _jsx(ChevronLeft, { className: "w-7 h-7" }) })), _jsx(IconBtn, { onClick: zoomOut, disabled: zoom <= MIN_ZOOM, ariaLabel: L.zoomOut, children: _jsx(ZoomOut, { className: "w-7 h-7" }) }), _jsxs(Span, { color: "inverse", size: "xs", className: "
|
|
34
|
+
return (_jsxs(Row, { gap: "xs", className: "bg-black/85 backdrop-blur-sm shrink-0 border-t border-white/10", padding: "inline", align: "center", justify: "center", wrap: true, children: [items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goPrev(); }, ariaLabel: L.prevImage, children: _jsx(ChevronLeft, { className: "w-7 h-7" }) })), _jsx(IconBtn, { onClick: zoomOut, disabled: zoom <= MIN_ZOOM, ariaLabel: L.zoomOut, children: _jsx(ZoomOut, { className: "w-7 h-7" }) }), _jsxs(Span, { color: "inverse-muted", size: "xs", className: "w-14 tabular-nums", align: "center", children: [Math.round(zoom * 100), "%"] }), _jsx(IconBtn, { onClick: zoomIn, disabled: zoom >= MAX_ZOOM, ariaLabel: L.zoomIn, children: _jsx(ZoomIn, { className: "w-7 h-7" }) }), zoom > 1 && (_jsx(IconBtn, { onClick: resetZoom, ariaLabel: L.resetZoom, children: _jsx(RotateCcw, { className: "w-7 h-7" }) })), _jsx(Span, { className: "w-px h-6 bg-white/15 mx-1 shrink-0", "aria-hidden": "true" }), _jsxs(Span, { color: "inverse-muted", size: "xs", className: "w-12 tabular-nums", align: "center", children: [index + 1, " / ", items.length] }), _jsx(Span, { className: "w-px h-6 bg-white/15 mx-1 shrink-0", "aria-hidden": "true" }), _jsx(IconBtn, { onClick: toggleFullscreen, ariaLabel: isFullscreen ? L.exitFullscreen : L.enterFullscreen, children: isFullscreen ? _jsx(Minimize, { className: "w-6 h-6" }) : _jsx(Maximize, { className: "w-6 h-6" }) }), _jsx(IconBtn, { onClick: onClose, ariaLabel: L.close, className: CLS_CLOSE_HOVER, children: _jsx(X, { className: "w-7 h-7" }) }), items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goNext(); }, ariaLabel: L.nextImage, children: _jsx(ChevronRight, { className: "w-7 h-7" }) }))] }));
|
|
35
35
|
}
|
|
36
36
|
function LightboxThumbnailStrip({ items, index, onSelect, resetZoom, L, }) {
|
|
37
37
|
return (_jsx(Row, { surface: "overlay-xl", className: "backdrop-blur-sm overflow-x-auto shrink-0", padding: "inline", justify: "center", gap: "sm", style: { paddingBottom: "calc(0.75rem + env(safe-area-inset-bottom, 0px))" }, children: items.map((item, i) => (_jsx(Button, { type: "button", onClick: () => { onSelect(i); resetZoom(); }, "aria-label": L.imageThumbnail(i + 1), "aria-current": i === index ? "true" : undefined, className: cn("relative shrink-0 w-14 h-14 p-[var(--appkit-space-0)] overflow-hidden rounded-lg border-2 transition-all active:scale-95", i === index ? "border-white opacity-100" : "border-transparent opacity-40 hover:opacity-75"), children: _jsx(MediaImage, { src: item.src, alt: item.alt, size: "thumbnail" }) }, i))) }));
|
|
@@ -95,5 +95,5 @@ export function ImageCropModal({ isOpen, imageUrl, onClose, onSave, initialCropD
|
|
|
95
95
|
left: `${position.x}%`,
|
|
96
96
|
top: `${position.y}%`,
|
|
97
97
|
transform: "translate(-50%, -50%)",
|
|
98
|
-
} }), _jsxs(Div, { className: "absolute inset-0 pointer-events-none", children: [_jsx(Div, { layout: "grid", className: "absolute w-full h-full grid-cols-3 grid-rows-3", children: Array.from({ length: 9 }).map((_, i) => (_jsx(Div, { className: "border border-white/20 border-[var(--appkit-color-border)]/30" }, i))) }), _jsxs(Row, { className: "absolute inset-0", align: "center", justify: "center", children: [_jsx(Div, { className: "w-6 h-px", surface: "default" }), _jsx(Div, { className: "absolute h-6 w-px", surface: "default" })] })] })] }), _jsxs(Stack, { gap: "xs", children: [_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "xs", weight: "medium", children: t("cropZoom") }), _jsxs(Text, { size: "xs", color: "muted", children: [Math.round(zoom * 100), "%"] })] }), _jsxs(Row, { gap: "3", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(Math.max(0.1, zoom - 0.1)), "aria-label": t("cropZoomOut"), children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM13 10H7" }) }) }), _jsx(MediaSlider, { value: zoom, min: 0.1, max: 3, step: 0.01, onChange: (v) => setZoom(v), className: "flex-1" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(Math.min(3, zoom + 0.1)), "aria-label": t("cropZoomIn"), children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7" }) }) })] }), _jsx(Row, { gap: "sm", children: [0.5, 1, 1.5, 2].map((preset) => (_jsxs(Button, { rounded: "lg", type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(preset), className: "px-[var(--appkit-space-3)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] bg-[var(--appkit-color-surface
|
|
98
|
+
} }), _jsxs(Div, { className: "absolute inset-0 pointer-events-none", children: [_jsx(Div, { layout: "grid", className: "absolute w-full h-full grid-cols-3 grid-rows-3", children: Array.from({ length: 9 }).map((_, i) => (_jsx(Div, { className: "border border-white/20 border-[var(--appkit-color-border)]/30" }, i))) }), _jsxs(Row, { className: "absolute inset-0", align: "center", justify: "center", children: [_jsx(Div, { className: "w-6 h-px", surface: "default" }), _jsx(Div, { className: "absolute h-6 w-px", surface: "default" })] })] })] }), _jsxs(Stack, { gap: "xs", children: [_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "xs", weight: "medium", children: t("cropZoom") }), _jsxs(Text, { size: "xs", color: "muted", children: [Math.round(zoom * 100), "%"] })] }), _jsxs(Row, { gap: "3", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(Math.max(0.1, zoom - 0.1)), "aria-label": t("cropZoomOut"), children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM13 10H7" }) }) }), _jsx(MediaSlider, { value: zoom, min: 0.1, max: 3, step: 0.01, onChange: (v) => setZoom(v), className: "flex-1" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(Math.min(3, zoom + 0.1)), "aria-label": t("cropZoomIn"), children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7" }) }) })] }), _jsx(Row, { gap: "sm", children: [0.5, 1, 1.5, 2].map((preset) => (_jsxs(Button, { rounded: "lg", type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(preset), className: "px-[var(--appkit-space-3)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] bg-[var(--appkit-color-surface-elevated)]", children: [preset * 100, "%"] }, preset))) })] }), showZoomWarning && (_jsxs(Alert, { variant: "warning", children: [_jsx(Span, { weight: "bold", children: t("cropWarningTitle") }), " ", t("cropWarningMessage")] })), _jsxs(Row, { textSize: "xs", justify: "between", className: "text-[var(--appkit-color-text-muted)]", children: [_jsxs(Span, { children: [t("cropPosition"), ": ", Math.round(position.x), "%, ", Math.round(position.y), "%"] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: handleReset, className: "text-primary-600 dark:text-primary-400 hover:underline", children: t("cropReset") })] }), _jsxs(Row, { gap: "sm", padding: "t-xs", children: [_jsx(Button, { onClick: handleSave, variant: "primary", className: "flex-1", children: t("cropSave") }), _jsx(Button, { onClick: onClose, variant: "secondary", className: "flex-1", children: t("cropCancel") })] })] }) }));
|
|
99
99
|
}
|
|
@@ -94,5 +94,5 @@ outputFormat = IMAGE_DOWNSCALE_FORMAT, outputQuality = IMAGE_DOWNSCALE_QUALITY,
|
|
|
94
94
|
{ label: "4:3", ratio: 4 / 3 },
|
|
95
95
|
{ label: "16:9", ratio: 16 / 9 },
|
|
96
96
|
{ label: "3:2", ratio: 3 / 2 },
|
|
97
|
-
].map((preset) => (_jsx(Button, { rounded: "lg", type: "button", variant: "ghost", size: "sm", onClick: () => applyAspectRatio(preset.ratio), className: "px-[var(--appkit-space-3)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] bg-[var(--appkit-color-surface
|
|
97
|
+
].map((preset) => (_jsx(Button, { rounded: "lg", type: "button", variant: "ghost", size: "sm", onClick: () => applyAspectRatio(preset.ratio), className: "px-[var(--appkit-space-3)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] bg-[var(--appkit-color-surface-elevated)]", children: preset.label }, preset.label))) })), _jsxs(Row, { gap: "sm", padding: "t-xs", children: [_jsx(Button, { onClick: handleSave, variant: "primary", className: "flex-1", disabled: saving, children: saving ? t("cropSaving") : t("cropSave") }), _jsx(Button, { onClick: onClose, variant: "secondary", className: "flex-1", children: t("cropCancel") })] })] }) }));
|
|
98
98
|
}
|