@mohasinac/appkit 4.30.18 → 4.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (557) hide show
  1. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +5 -2
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -3
  3. package/dist/_internal/client/features/layout/useSidebarSearch.d.ts +21 -5
  4. package/dist/_internal/client/features/layout/useSidebarSearch.js +27 -6
  5. package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +23 -3
  6. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +106 -86
  7. package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +16 -5
  8. package/dist/_internal/client/features/lottery/LotteryPullForm.js +65 -40
  9. package/dist/_internal/client/features/maintenance/views/AnalysisRunnerView.js +5 -2
  10. package/dist/_internal/client/features/maintenance/views/CloudLogsListView.js +11 -3
  11. package/dist/_internal/client/hand-mode/HandModeProvider.js +2 -0
  12. package/dist/_internal/server/features/auctions/actions.js +14 -3
  13. package/dist/_internal/server/features/auctions/service.js +1 -1
  14. package/dist/_internal/server/features/auth/permissions.d.ts +2 -0
  15. package/dist/_internal/server/features/auth/permissions.js +3 -2
  16. package/dist/_internal/server/features/blog/data.js +2 -2
  17. package/dist/_internal/server/features/blog/service.js +3 -3
  18. package/dist/_internal/server/features/brands/data.js +1 -1
  19. package/dist/_internal/server/features/brands/service.js +3 -3
  20. package/dist/_internal/server/features/bundles/actions.js +6 -1
  21. package/dist/_internal/server/features/bundles/data.js +21 -4
  22. package/dist/_internal/server/features/cart/data.js +3 -1
  23. package/dist/_internal/server/features/cart/service.js +13 -2
  24. package/dist/_internal/server/features/categories/data.js +26 -6
  25. package/dist/_internal/server/features/classified/index.d.ts +0 -1
  26. package/dist/_internal/server/features/classified/index.js +0 -1
  27. package/dist/_internal/server/features/digital-code/index.d.ts +0 -1
  28. package/dist/_internal/server/features/digital-code/index.js +0 -1
  29. package/dist/_internal/server/features/events/actions.js +17 -4
  30. package/dist/_internal/server/features/events/data.js +1 -1
  31. package/dist/_internal/server/features/events/service.js +1 -1
  32. package/dist/_internal/server/features/grouped/data.js +7 -2
  33. package/dist/_internal/server/features/item-requests/data.js +1 -1
  34. package/dist/_internal/server/features/live/index.d.ts +0 -1
  35. package/dist/_internal/server/features/live/index.js +0 -1
  36. package/dist/_internal/server/features/lottery/actions.js +2 -2
  37. package/dist/_internal/server/features/lottery/data.js +1 -1
  38. package/dist/_internal/server/features/orders/actions.js +7 -7
  39. package/dist/_internal/server/features/orders/data.d.ts +1 -1
  40. package/dist/_internal/server/features/orders/data.js +14 -2
  41. package/dist/_internal/server/features/orders/service.js +1 -1
  42. package/dist/_internal/server/features/pre-orders/service.js +1 -1
  43. package/dist/_internal/server/features/prize-draws/actions.js +1 -1
  44. package/dist/_internal/server/features/products/data.js +21 -6
  45. package/dist/_internal/server/features/products/list-public.d.ts +9 -0
  46. package/dist/_internal/server/features/products/list-public.js +95 -7
  47. package/dist/_internal/server/features/products/service.js +1 -1
  48. package/dist/_internal/server/features/promotions/actions.js +1 -1
  49. package/dist/_internal/server/features/promotions/data.js +1 -1
  50. package/dist/_internal/server/features/promotions/service.js +1 -1
  51. package/dist/_internal/server/features/reviews/data.d.ts +1 -1
  52. package/dist/_internal/server/features/reviews/data.js +6 -1
  53. package/dist/_internal/server/features/reviews/og-data.js +1 -1
  54. package/dist/_internal/server/features/shared/listing-data-factory.js +7 -2
  55. package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
  56. package/dist/_internal/server/features/site-settings/adapters.js +8 -5
  57. package/dist/_internal/server/features/stores/data.js +1 -1
  58. package/dist/_internal/server/features/sublisting-categories/data.js +1 -1
  59. package/dist/_internal/server/features/tester/visibility.d.ts +2 -1
  60. package/dist/_internal/server/features/tester/visibility.js +2 -2
  61. package/dist/_internal/server/functions/scheduled.d.ts +3 -1
  62. package/dist/_internal/server/functions/scheduled.js +27 -1
  63. package/dist/_internal/server/jobs/core/auctionSettlement.js +6 -1
  64. package/dist/_internal/server/jobs/core/hardBanCascade.js +4 -0
  65. package/dist/_internal/server/jobs/core/index.d.ts +2 -0
  66. package/dist/_internal/server/jobs/core/index.js +2 -0
  67. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +7 -15
  68. package/dist/_internal/server/jobs/core/pageViewPrune.d.ts +10 -0
  69. package/dist/_internal/server/jobs/core/pageViewPrune.js +44 -0
  70. package/dist/_internal/server/jobs/core/pageViewRollup.d.ts +2 -0
  71. package/dist/_internal/server/jobs/core/pageViewRollup.js +87 -0
  72. package/dist/_internal/server/jobs/core/revenueRollup.js +7 -1
  73. package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
  74. package/dist/_internal/server/jobs/handlers/index.js +2 -0
  75. package/dist/_internal/server/jobs/handlers/pageViewPrune.d.ts +2 -0
  76. package/dist/_internal/server/jobs/handlers/pageViewPrune.js +2 -0
  77. package/dist/_internal/server/jobs/handlers/pageViewRollup.d.ts +2 -0
  78. package/dist/_internal/server/jobs/handlers/pageViewRollup.js +2 -0
  79. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  80. package/dist/_internal/shared/actions/action-registry.js +69 -22
  81. package/dist/_internal/shared/checkout/rules/classified.rule.d.ts +9 -4
  82. package/dist/_internal/shared/checkout/rules/classified.rule.js +7 -2
  83. package/dist/_internal/shared/features/layout/matchesNavQuery.d.ts +14 -0
  84. package/dist/_internal/shared/features/layout/matchesNavQuery.js +72 -0
  85. package/dist/_internal/shared/features/layout/types.d.ts +37 -1
  86. package/dist/_internal/shared/features/layout/types.js +19 -1
  87. package/dist/_internal/shared/features/notifications/action-url.d.ts +9 -1
  88. package/dist/_internal/shared/features/notifications/action-url.js +47 -0
  89. package/dist/_internal/shared/features/offers/config.d.ts +65 -0
  90. package/dist/_internal/shared/features/offers/config.js +73 -2
  91. package/dist/_internal/shared/features/orders/schema.d.ts +19 -1
  92. package/dist/_internal/shared/features/orders/schema.js +22 -2
  93. package/dist/_internal/shared/features/site-settings/types.d.ts +12 -3
  94. package/dist/_internal/shared/listing-types/capabilities.d.ts +8 -2
  95. package/dist/_internal/shared/listing-types/capabilities.js +6 -1
  96. package/dist/_internal/shared/listing-types/classified/ctas.js +6 -1
  97. package/dist/_internal/shared/listing-types/feature-flags.d.ts +10 -5
  98. package/dist/_internal/shared/listing-types/feature-flags.js +11 -6
  99. package/dist/client/api/useApiQuery.js +17 -6
  100. package/dist/client.d.ts +38 -20
  101. package/dist/client.js +39 -14
  102. package/dist/configs/next.js +10 -2
  103. package/dist/constants/api-endpoints.d.ts +18 -54
  104. package/dist/constants/api-endpoints.js +6 -26
  105. package/dist/constants/field-names.d.ts +6 -24
  106. package/dist/constants/field-names.js +10 -27
  107. package/dist/constants/geo/countries.d.ts +50 -0
  108. package/dist/constants/geo/countries.js +129 -0
  109. package/dist/constants/geo/subdivisions.d.ts +13 -0
  110. package/dist/constants/geo/subdivisions.js +104 -0
  111. package/dist/constants/index.d.ts +2 -2
  112. package/dist/constants/index.js +2 -2
  113. package/dist/constants/table-keys.d.ts +24 -0
  114. package/dist/constants/table-keys.js +28 -0
  115. package/dist/contracts/client-realtime.d.ts +6 -0
  116. package/dist/contracts/extend.d.ts +0 -9
  117. package/dist/contracts/index.d.ts +1 -1
  118. package/dist/contracts/realtime-session.d.ts +12 -12
  119. package/dist/contracts/realtime-session.js +79 -77
  120. package/dist/core/browser.d.ts +1 -1
  121. package/dist/core/browser.js +1 -1
  122. package/dist/core/index.d.ts +1 -1
  123. package/dist/core/index.js +1 -1
  124. package/dist/core/site-config.d.ts +0 -3
  125. package/dist/core/site-config.js +0 -3
  126. package/dist/errors/index.d.ts +1 -1
  127. package/dist/errors/index.js +1 -1
  128. package/dist/errors/messages.d.ts +0 -8
  129. package/dist/errors/messages.js +0 -9
  130. package/dist/features/about/components/DeveloperView.js +7 -2
  131. package/dist/features/about/components/PolicyPageView.js +9 -1
  132. package/dist/features/about/components/PublicProfileView.js +23 -5
  133. package/dist/features/about/schemas/index.d.ts +8 -8
  134. package/dist/features/account/components/AddressFilters.js +32 -11
  135. package/dist/features/account/components/AddressForm.d.ts +26 -25
  136. package/dist/features/account/components/AddressForm.js +81 -103
  137. package/dist/features/account/components/AddressesIndexListing.js +8 -4
  138. package/dist/features/account/components/NotificationBell.js +4 -3
  139. package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
  140. package/dist/features/account/components/UserOffersPanel.js +1 -1
  141. package/dist/features/account/components/UserSidebar.d.ts +3 -4
  142. package/dist/features/account/components/UserSupportView.js +89 -58
  143. package/dist/features/account/components/index.d.ts +1 -7
  144. package/dist/features/account/components/index.js +0 -3
  145. package/dist/features/account/hooks/useAddresses.d.ts +4 -3
  146. package/dist/features/account/hooks/useAddresses.js +4 -6
  147. package/dist/features/account/hooks/useCollapsedSections.d.ts +51 -10
  148. package/dist/features/account/hooks/useCollapsedSections.js +211 -38
  149. package/dist/features/account/hooks/useProfile.d.ts +8 -0
  150. package/dist/features/account/index.d.ts +0 -3
  151. package/dist/features/account/index.js +0 -3
  152. package/dist/features/account/schemas/index.d.ts +0 -92
  153. package/dist/features/account/schemas/index.js +42 -20
  154. package/dist/features/addresses/components/AddressLocationFields.d.ts +13 -0
  155. package/dist/features/addresses/components/AddressLocationFields.js +41 -0
  156. package/dist/features/addresses/hooks/usePostalLookup.d.ts +17 -0
  157. package/dist/features/addresses/hooks/usePostalLookup.js +133 -0
  158. package/dist/features/addresses/schemas/address-form.d.ts +423 -0
  159. package/dist/features/addresses/schemas/address-form.js +212 -0
  160. package/dist/features/addresses/schemas/index.d.ts +1 -0
  161. package/dist/features/addresses/schemas/index.js +8 -0
  162. package/dist/features/admin/actions/admin-read-actions.d.ts +1 -1
  163. package/dist/features/admin/actions/index.d.ts +0 -1
  164. package/dist/features/admin/actions/index.js +0 -1
  165. package/dist/features/admin/actions/notification-actions.js +1 -41
  166. package/dist/features/admin/components/AdminActionIndexView.d.ts +32 -0
  167. package/dist/features/admin/components/AdminActionIndexView.js +128 -0
  168. package/dist/features/admin/components/AdminAdEditorView.js +159 -163
  169. package/dist/features/admin/components/AdminAddressEditorView.js +97 -55
  170. package/dist/features/admin/components/AdminBrandEditorView.d.ts +15 -0
  171. package/dist/features/admin/components/AdminBrandEditorView.js +113 -77
  172. package/dist/features/admin/components/AdminBundleEditorView.d.ts +19 -9
  173. package/dist/features/admin/components/AdminBundleEditorView.js +136 -168
  174. package/dist/features/admin/components/AdminCategoryEditorView.js +120 -43
  175. package/dist/features/admin/components/AdminCouponEditorView.js +145 -109
  176. package/dist/features/admin/components/AdminEmployeeEditorView.js +125 -56
  177. package/dist/features/admin/components/AdminFaqEditorView.js +112 -58
  178. package/dist/features/admin/components/AdminFeatureEditorView.js +108 -68
  179. package/dist/features/admin/components/AdminFulfillmentView.js +5 -2
  180. package/dist/features/admin/components/AdminMediaView.js +3 -3
  181. package/dist/features/admin/components/AdminNavEditorView.js +69 -44
  182. package/dist/features/admin/components/AdminOrderEditorView.js +47 -10
  183. package/dist/features/admin/components/AdminPrizeDrawsView.js +16 -2
  184. package/dist/features/admin/components/AdminSidebar.d.ts +11 -7
  185. package/dist/features/admin/components/AdminSiteSettingsView.js +37 -37
  186. package/dist/features/admin/components/AdminStoreEditorView.js +75 -52
  187. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +71 -30
  188. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +95 -65
  189. package/dist/features/admin/components/BrandQuickCreateForm.d.ts +10 -0
  190. package/dist/features/admin/components/BrandQuickCreateForm.js +49 -26
  191. package/dist/features/admin/components/CategoryQuickCreateForm.d.ts +11 -0
  192. package/dist/features/admin/components/CategoryQuickCreateForm.js +48 -26
  193. package/dist/features/admin/components/index.d.ts +2 -2
  194. package/dist/features/admin/components/index.js +1 -1
  195. package/dist/features/admin/constants/site-settings-tabs.d.ts +120 -0
  196. package/dist/features/admin/constants/site-settings-tabs.js +152 -0
  197. package/dist/features/admin/index.d.ts +0 -3
  198. package/dist/features/admin/index.js +0 -2
  199. package/dist/features/admin/repository/analytics-rollup.repository.d.ts +35 -0
  200. package/dist/features/admin/repository/analytics-rollup.repository.js +30 -0
  201. package/dist/features/admin/schemas/admin-editor-forms.d.ts +56 -57
  202. package/dist/features/admin/schemas/admin-editor-forms.js +97 -54
  203. package/dist/features/admin/schemas/admin-ops-forms.d.ts +57 -5
  204. package/dist/features/admin/schemas/admin-ops-forms.js +104 -20
  205. package/dist/features/admin/schemas/admin-user-form.js +7 -0
  206. package/dist/features/admin/schemas/firestore.d.ts +48 -95
  207. package/dist/features/admin/schemas/firestore.js +15 -151
  208. package/dist/features/admin/schemas/nav-item-form.js +9 -2
  209. package/dist/features/admin/server.d.ts +0 -4
  210. package/dist/features/admin/server.js +0 -2
  211. package/dist/features/admin/types/index.d.ts +0 -7
  212. package/dist/features/analytics/repository/page-views.repository.d.ts +14 -0
  213. package/dist/features/analytics/repository/page-views.repository.js +24 -0
  214. package/dist/features/analytics/types.d.ts +1 -1
  215. package/dist/features/analytics/types.js +13 -0
  216. package/dist/features/auctions/components/AuctionDetailPageView.js +6 -2
  217. package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -1
  218. package/dist/features/auth/actions/index.d.ts +0 -1
  219. package/dist/features/auth/actions/index.js +0 -1
  220. package/dist/features/auth/actions/profile-actions.js +4 -3
  221. package/dist/features/auth/actions/realtime-token-actions.js +1 -12
  222. package/dist/features/auth/auth-helpers.js +5 -7
  223. package/dist/features/auth/components/ForgotPasswordView.js +1 -1
  224. package/dist/features/auth/components/Guards.js +2 -1
  225. package/dist/features/auth/components/LoginForm.d.ts +0 -2
  226. package/dist/features/auth/components/LoginForm.js +2 -4
  227. package/dist/features/auth/components/RegisterForm.js +62 -19
  228. package/dist/features/auth/components/ResetPasswordView.js +1 -1
  229. package/dist/features/auth/hooks/useAuth.js +3 -0
  230. package/dist/features/auth/permissions/constants.d.ts +27 -1
  231. package/dist/features/auth/role-predicates.d.ts +75 -7
  232. package/dist/features/auth/role-predicates.js +28 -2
  233. package/dist/features/auth/schemas/firestore.d.ts +22 -0
  234. package/dist/features/auth/schemas/index.d.ts +1 -1
  235. package/dist/features/auth/schemas/index.js +44 -8
  236. package/dist/features/auth/types/index.d.ts +14 -1
  237. package/dist/features/blog/api/route.js +10 -2
  238. package/dist/features/blog/components/BlogIndexListing.js +1 -1
  239. package/dist/features/blog/hooks/useBlog.js +2 -2
  240. package/dist/features/blog/repository/blog.repository.js +3 -1
  241. package/dist/features/blog/schemas/index.d.ts +4 -0
  242. package/dist/features/blog/schemas/index.js +2 -0
  243. package/dist/features/blog/types/index.d.ts +1 -1
  244. package/dist/features/cart/actions/cart-actions.js +13 -4
  245. package/dist/features/cart/utils/pending-ops.js +1 -1
  246. package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +22 -0
  247. package/dist/features/catalogue/components/CatalogueItemEditorView.js +112 -52
  248. package/dist/features/catalogue/schemas/validation.d.ts +4 -4
  249. package/dist/features/catalogue/schemas/validation.js +47 -10
  250. package/dist/features/categories/components/BrandDetailPageView.js +28 -12
  251. package/dist/features/categories/components/CategoryDetailPageView.js +37 -20
  252. package/dist/features/categories/repository/categories.repository.js +3 -1
  253. package/dist/features/categories/schemas/bundle-form.d.ts +142 -0
  254. package/dist/features/categories/schemas/bundle-form.js +149 -0
  255. package/dist/features/checkout/actions/checkout-value-otp-actions.js +10 -1
  256. package/dist/features/classified/components/ClassifiedContactSellerPanel.js +1 -1
  257. package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +5 -4
  258. package/dist/features/classified/components/ClassifiedDetailPageView.js +47 -18
  259. package/dist/features/consultation/components/ConsultationForm.js +1 -1
  260. package/dist/features/consultation/schemas/index.js +34 -10
  261. package/dist/features/corporate/schemas/index.js +36 -15
  262. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +4 -1
  263. package/dist/features/events/components/EventBanner.js +5 -2
  264. package/dist/features/events/components/EventOfferCard.js +3 -1
  265. package/dist/features/events/components/EventPollWidget.js +1 -1
  266. package/dist/features/events/components/SpinWheelView.js +3 -2
  267. package/dist/features/filters/FilterPanel.js +3 -3
  268. package/dist/features/filters/RangeFilter.d.ts +10 -0
  269. package/dist/features/filters/RangeFilter.js +41 -4
  270. package/dist/features/grouped/components/GroupedListingEditorView.js +2 -1
  271. package/dist/features/history/hooks/useHistory.js +29 -27
  272. package/dist/features/homepage/components/AdSlot.js +3 -1
  273. package/dist/features/homepage/components/GoogleReviewsSection.js +8 -2
  274. package/dist/features/homepage/components/MarketplaceHomepageView.js +58 -15
  275. package/dist/features/homepage/components/SocialFeedSection.js +4 -1
  276. package/dist/features/homepage/hooks/useBlogArticles.js +1 -1
  277. package/dist/features/homepage/lib/live-stats.js +8 -1
  278. package/dist/features/homepage/repository/carousel.repository.js +2 -1
  279. package/dist/features/layout/BottomActions.js +84 -11
  280. package/dist/features/layout/BottomActionsContext.d.ts +1 -6
  281. package/dist/features/layout/BottomActionsContext.js +1 -1
  282. package/dist/features/layout/hooks/useBottomActions.js +2 -2
  283. package/dist/features/layout/hooks/useFormBottomActions.d.ts +12 -1
  284. package/dist/features/layout/hooks/useFormBottomActions.js +12 -6
  285. package/dist/features/live/components/LiveItemDetailPageView.js +4 -1
  286. package/dist/features/lottery/schemas/config-write.d.ts +9 -5
  287. package/dist/features/lottery/schemas/config-write.js +69 -9
  288. package/dist/features/media/finalize.js +3 -1
  289. package/dist/features/media/modals/ImageEditor.js +1 -1
  290. package/dist/features/media/modals/VideoThumbnailSelector.js +5 -2
  291. package/dist/features/media/modals/VideoTrimModal.js +5 -2
  292. package/dist/features/media/upload/MediaUploadField.js +2 -2
  293. package/dist/features/messages/hooks/useConversation.js +18 -4
  294. package/dist/features/messages/hooks/useConversations.js +25 -8
  295. package/dist/features/orders/components/RefundRequestView.js +5 -2
  296. package/dist/features/orders/schemas/buyer-forms.d.ts +6 -3
  297. package/dist/features/orders/schemas/buyer-forms.js +31 -3
  298. package/dist/features/orders/schemas/index.d.ts +2 -2
  299. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -1
  300. package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
  301. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -1
  302. package/dist/features/products/components/GroupSettingsPanel.js +3 -1
  303. package/dist/features/products/components/MakeOfferButton.d.ts +13 -2
  304. package/dist/features/products/components/MakeOfferButton.js +33 -11
  305. package/dist/features/products/components/PrizeDrawDetailPageView.js +4 -1
  306. package/dist/features/products/components/ProductDetailActions.js +0 -1
  307. package/dist/features/products/components/ProductDetailPageView.d.ts +7 -3
  308. package/dist/features/products/components/ProductDetailPageView.js +16 -7
  309. package/dist/features/products/components/ShareButton.js +3 -1
  310. package/dist/features/products/constants/action-defs.d.ts +1 -2
  311. package/dist/features/products/constants/action-defs.js +40 -43
  312. package/dist/features/products/repository/loadProductFeatures.js +10 -2
  313. package/dist/features/products/repository/products.repository.d.ts +5 -1
  314. package/dist/features/products/repository/products.repository.js +25 -2
  315. package/dist/features/products/schemas/firestore.d.ts +7 -3
  316. package/dist/features/products/schemas/product-features.validators.js +3 -0
  317. package/dist/features/promotions/components/CouponCard.js +11 -8
  318. package/dist/features/reviews/actions/review-actions.js +8 -1
  319. package/dist/features/reviews/components/ReviewDetailPageView.js +13 -3
  320. package/dist/features/reviews/components/ReviewDetailShell.js +3 -1
  321. package/dist/features/scams/actions/scam-actions.d.ts +9 -1
  322. package/dist/features/scams/actions/scam-actions.js +52 -12
  323. package/dist/features/scams/components/SellerTrustBadge.d.ts +1 -1
  324. package/dist/features/scams/components/SellerTrustBadge.js +13 -0
  325. package/dist/features/scams/repository/scammer.repository.js +2 -1
  326. package/dist/features/scams/schemas/firestore.d.ts +15 -1
  327. package/dist/features/scams/schemas/report-form.d.ts +5 -5
  328. package/dist/features/scams/schemas/report-form.js +18 -3
  329. package/dist/features/search/action-index/derive.d.ts +49 -0
  330. package/dist/features/search/action-index/derive.js +121 -0
  331. package/dist/features/search/action-index/repository.d.ts +42 -0
  332. package/dist/features/search/action-index/repository.js +100 -0
  333. package/dist/features/search/action-index/settings-entries.d.ts +41 -0
  334. package/dist/features/search/action-index/settings-entries.js +268 -0
  335. package/dist/features/search/action-index/types.d.ts +81 -0
  336. package/dist/features/search/action-index/types.js +102 -0
  337. package/dist/features/search/action-index/validate-entry.d.ts +34 -0
  338. package/dist/features/search/action-index/validate-entry.js +114 -0
  339. package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
  340. package/dist/features/search/hooks/useNavSuggestions.js +23 -3
  341. package/dist/features/search/repository/search.repository.js +3 -1
  342. package/dist/features/seller/actions/offer-actions.js +43 -19
  343. package/dist/features/seller/actions/seller-actions.js +29 -5
  344. package/dist/features/seller/components/CategoryChipPicker.d.ts +9 -0
  345. package/dist/features/seller/components/CategoryChipPicker.js +12 -0
  346. package/dist/features/seller/components/FulfillmentView.js +5 -2
  347. package/dist/features/seller/components/PhysicalLocationModal.js +1 -1
  348. package/dist/features/seller/components/PrintCenterView.js +3 -1
  349. package/dist/features/seller/components/SellerAddressesView.js +5 -1
  350. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +83 -43
  351. package/dist/features/seller/components/SellerArtView.d.ts +14 -7
  352. package/dist/features/seller/components/SellerArtView.js +4 -119
  353. package/dist/features/seller/components/SellerBidsView.js +1 -1
  354. package/dist/features/seller/components/SellerClassifiedView.d.ts +14 -7
  355. package/dist/features/seller/components/SellerClassifiedView.js +4 -124
  356. package/dist/features/seller/components/SellerCouponEditorView.d.ts +22 -1
  357. package/dist/features/seller/components/SellerCouponEditorView.js +91 -45
  358. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  359. package/dist/features/seller/components/SellerDigitalCodesView.d.ts +14 -7
  360. package/dist/features/seller/components/SellerDigitalCodesView.js +4 -126
  361. package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
  362. package/dist/features/seller/components/SellerListingTypeView.d.ts +66 -0
  363. package/dist/features/seller/components/SellerListingTypeView.js +277 -0
  364. package/dist/features/seller/components/SellerLiveView.d.ts +14 -7
  365. package/dist/features/seller/components/SellerLiveView.js +4 -126
  366. package/dist/features/seller/components/SellerOrdersView.js +3 -3
  367. package/dist/features/seller/components/SellerPayoutMethodsView.js +2 -2
  368. package/dist/features/seller/components/SellerProductShell.d.ts +5 -0
  369. package/dist/features/seller/components/SellerProductShell.js +15 -5
  370. package/dist/features/seller/components/SellerProductsView.js +24 -10
  371. package/dist/features/seller/components/SellerReviewsView.js +47 -16
  372. package/dist/features/seller/components/SellerShippingConfigsView.js +5 -4
  373. package/dist/features/seller/components/SellerSidebar.d.ts +3 -6
  374. package/dist/features/seller/components/SellerStickersView.d.ts +14 -7
  375. package/dist/features/seller/components/SellerStickersView.js +4 -119
  376. package/dist/features/seller/components/SellerStoreCategoriesView.js +3 -2
  377. package/dist/features/seller/components/SellerSupportView.d.ts +31 -0
  378. package/dist/features/seller/components/SellerSupportView.js +100 -0
  379. package/dist/features/seller/components/index.d.ts +4 -8
  380. package/dist/features/seller/components/index.js +2 -4
  381. package/dist/features/seller/index.d.ts +0 -1
  382. package/dist/features/seller/index.js +0 -1
  383. package/dist/features/seller/schemas/coupon-form.d.ts +214 -0
  384. package/dist/features/seller/schemas/coupon-form.js +155 -23
  385. package/dist/features/seller/schemas/offer-forms.d.ts +16 -7
  386. package/dist/features/seller/schemas/offer-forms.js +28 -12
  387. package/dist/features/shell/FormShell.js +2 -2
  388. package/dist/features/shell/QuickFormDrawer.js +2 -2
  389. package/dist/features/shell/SectionForm.d.ts +19 -1
  390. package/dist/features/shell/SectionForm.js +104 -17
  391. package/dist/features/shell/build-sections.d.ts +23 -0
  392. package/dist/features/shell/build-sections.js +106 -8
  393. package/dist/features/shell/field-ui-meta.d.ts +44 -0
  394. package/dist/features/shell/field-ui-meta.js +14 -7
  395. package/dist/features/shell/form-sections.d.ts +46 -0
  396. package/dist/features/shell/form-sections.js +114 -0
  397. package/dist/features/shipments/components/AdminShipmentEditorView.js +87 -64
  398. package/dist/features/shipments/schemas/validation.d.ts +2 -2
  399. package/dist/features/shipments/schemas/validation.js +44 -13
  400. package/dist/features/store-extensions/schemas/custom-role-form.js +6 -2
  401. package/dist/features/store-extensions/schemas/listing-template-form.d.ts +7 -7
  402. package/dist/features/store-extensions/schemas/payout-method-form.js +14 -0
  403. package/dist/features/stores/actions/store-query-actions.js +3 -2
  404. package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -1
  405. package/dist/features/stores/api/[storeSlug]/products/route.js +3 -1
  406. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  407. package/dist/features/stores/components/StoreDetailLayoutView.js +12 -3
  408. package/dist/features/support/repository/support.repository.d.ts +21 -0
  409. package/dist/features/support/repository/support.repository.js +63 -0
  410. package/dist/features/support/schemas/firestore.d.ts +27 -2
  411. package/dist/features/support/schemas/firestore.js +2 -0
  412. package/dist/features/support/schemas/ticket-create-form.js +7 -0
  413. package/dist/features/tester/schemas/checklist-item-form.d.ts +43 -0
  414. package/dist/features/tester/schemas/checklist-item-form.js +109 -0
  415. package/dist/features/tester/seed-data/blog-tester-seed-data.js +2 -2
  416. package/dist/features/tester/seed-data/categories-tester-seed-data.js +2 -2
  417. package/dist/features/tester/seed-data/events-tester-seed-data.js +5 -5
  418. package/dist/features/tester/seed-data/orders-tester-seed-data.js +2 -2
  419. package/dist/features/tester/seed-data/products-tester-seed-data.js +48 -49
  420. package/dist/features/tester/seed-data/stores-tester-seed-data.js +3 -3
  421. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +291 -30
  422. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +51 -14
  423. package/dist/features/wishlist/hooks/useWishlistToggle.js +8 -1
  424. package/dist/http/api-handler.js +2 -1
  425. package/dist/index.d.ts +25 -104
  426. package/dist/index.js +38 -143
  427. package/dist/jobs.d.ts +1 -1
  428. package/dist/jobs.js +1 -1
  429. package/dist/monitoring/browser.d.ts +0 -2
  430. package/dist/monitoring/browser.js +12 -1
  431. package/dist/monitoring/index.d.ts +0 -2
  432. package/dist/monitoring/index.js +0 -1
  433. package/dist/next/api/routeHandler.js +9 -4
  434. package/dist/next/index.d.ts +1 -2
  435. package/dist/next/index.js +0 -1
  436. package/dist/next/middleware/index.d.ts +0 -2
  437. package/dist/next/middleware/index.js +0 -1
  438. package/dist/next/routing/route-map.d.ts +8 -7
  439. package/dist/next/routing/route-map.js +10 -3
  440. package/dist/providers/auth-firebase/session.js +3 -1
  441. package/dist/providers/db-firebase/admin-app-lite.js +8 -8
  442. package/dist/providers/db-firebase/admin.js +27 -13
  443. package/dist/providers/db-firebase/browser-stub.d.ts +1 -11
  444. package/dist/providers/db-firebase/browser-stub.js +6 -11
  445. package/dist/providers/db-firebase/index.d.ts +0 -1
  446. package/dist/providers/db-firebase/index.js +0 -1
  447. package/dist/providers/db-firebase/rtdb-paths.d.ts +15 -6
  448. package/dist/providers/db-firebase/rtdb-paths.js +15 -6
  449. package/dist/providers/db-firebase/rtdb-url.d.ts +27 -0
  450. package/dist/providers/db-firebase/rtdb-url.js +50 -0
  451. package/dist/providers/db-firebase/sieve.d.ts +22 -0
  452. package/dist/providers/firebase-client/realtime.d.ts +20 -0
  453. package/dist/providers/firebase-client/realtime.js +34 -1
  454. package/dist/providers.d.ts +1 -1
  455. package/dist/providers.js +1 -1
  456. package/dist/react/hooks/use-action-dispatch.js +8 -2
  457. package/dist/react/hooks/useFormStatePreservation.js +3 -1
  458. package/dist/react/hooks/useListingTypeFlags.d.ts +1 -1
  459. package/dist/react/hooks/useListingTypeFlags.js +1 -1
  460. package/dist/react/hooks/usePendingFilters.js +5 -3
  461. package/dist/react/hooks/usePendingTable.js +15 -3
  462. package/dist/react/hooks/useRealtimeEvent.js +20 -9
  463. package/dist/repositories/index.d.ts +0 -1
  464. package/dist/repositories/index.js +0 -1
  465. package/dist/schemas/registry.d.ts +197 -232
  466. package/dist/schemas/registry.js +5 -6
  467. package/dist/schemas/webhooks/razorpay.d.ts +50 -50
  468. package/dist/security/authorization.d.ts +9 -0
  469. package/dist/security/authorization.js +16 -2
  470. package/dist/security/browser.d.ts +1 -3
  471. package/dist/security/browser.js +5 -2
  472. package/dist/security/index.d.ts +1 -3
  473. package/dist/security/index.js +19 -2
  474. package/dist/security/pii-encrypt.js +16 -0
  475. package/dist/security/pii-schemas.d.ts +0 -14
  476. package/dist/security/pii-schemas.js +7 -15
  477. package/dist/seed/_helpers/category-forest.js +2 -2
  478. package/dist/seed/_helpers/media.d.ts +19 -0
  479. package/dist/seed/_helpers/media.js +75 -0
  480. package/dist/seed/blog-posts-seed-data.js +17 -17
  481. package/dist/seed/carousel-slides-seed-data.js +7 -7
  482. package/dist/seed/cart-seed-data.js +13 -13
  483. package/dist/seed/categories-seed-data.js +10 -10
  484. package/dist/seed/events-seed-data.js +24 -24
  485. package/dist/seed/factories/product.factory.js +4 -4
  486. package/dist/seed/factories/store.factory.js +3 -3
  487. package/dist/seed/factories/user.factory.js +2 -2
  488. package/dist/seed/grouped-listings-seed-data.js +11 -11
  489. package/dist/seed/homepage-sections-seed-data.js +2 -2
  490. package/dist/seed/index.d.ts +0 -1
  491. package/dist/seed/index.js +0 -1
  492. package/dist/seed/manifest.d.ts +1 -1
  493. package/dist/seed/manifest.js +0 -5
  494. package/dist/seed/notifications-seed-data.js +20 -1
  495. package/dist/seed/orders-seed-data.js +2 -2
  496. package/dist/seed/products-art-seed-data.js +16 -16
  497. package/dist/seed/products-auctions-seed-data.js +34 -34
  498. package/dist/seed/products-classifieds-seed-data.js +35 -37
  499. package/dist/seed/products-digital-codes-seed-data.js +20 -20
  500. package/dist/seed/products-live-items-seed-data.js +11 -11
  501. package/dist/seed/products-preorders-seed-data.js +13 -13
  502. package/dist/seed/products-prize-draws-seed-data.js +43 -43
  503. package/dist/seed/products-standard-seed-data.js +54 -54
  504. package/dist/seed/products-stickers-seed-data.js +15 -15
  505. package/dist/seed/reviews-seed-data.js +4 -4
  506. package/dist/seed/scammers-seed-data.js +3 -3
  507. package/dist/seed/site-settings-seed-data.js +11 -24
  508. package/dist/seed/store-extensions-seed-data.js +10 -10
  509. package/dist/seed/stores-seed-data.js +11 -11
  510. package/dist/seed/support-tickets-seed-data.d.ts +14 -0
  511. package/dist/seed/support-tickets-seed-data.js +20 -1
  512. package/dist/seed/users-seed-data.js +20 -20
  513. package/dist/server-entry.d.ts +0 -1
  514. package/dist/server-entry.js +0 -1
  515. package/dist/server.d.ts +9 -6
  516. package/dist/server.js +7 -13
  517. package/dist/styles.css +248 -68
  518. package/dist/tailwind-utilities.css +1 -1
  519. package/dist/tokens/themes/default-dark.js +2 -2
  520. package/dist/tokens/themes/default-light.js +2 -2
  521. package/dist/tokens/tokens.css +24 -4
  522. package/dist/ui/components/ActionRow.d.ts +50 -0
  523. package/dist/ui/components/ActionRow.js +53 -0
  524. package/dist/ui/components/ActionRow.style.css +145 -0
  525. package/dist/ui/components/Drawer.d.ts +10 -0
  526. package/dist/ui/components/Drawer.js +2 -1
  527. package/dist/ui/components/FilterDrawer.js +4 -1
  528. package/dist/ui/components/FilterDrawer.style.css +6 -12
  529. package/dist/ui/components/FormActionBar.js +14 -1
  530. package/dist/ui/components/FormActionBar.style.css +12 -11
  531. package/dist/ui/components/ListingLayout.js +8 -1
  532. package/dist/ui/components/ListingLayout.style.css +6 -13
  533. package/dist/ui/components/Modal.d.ts +15 -1
  534. package/dist/ui/components/Modal.js +17 -3
  535. package/dist/ui/components/QuickCreateModal.js +2 -2
  536. package/dist/ui/components/QuickCreateModal.style.css +78 -84
  537. package/dist/ui/components/RecordDetailModal.js +2 -2
  538. package/dist/ui/components/SideDrawer.d.ts +8 -0
  539. package/dist/ui/components/SideDrawer.js +2 -1
  540. package/dist/ui/components/SideDrawer.style.css +6 -3
  541. package/dist/ui/components/SideModal.d.ts +11 -1
  542. package/dist/ui/components/SideModal.js +3 -2
  543. package/dist/ui/components/SideModal.style.css +14 -0
  544. package/dist/ui/components/Typography.style.css +33 -24
  545. package/dist/ui/components/index.style.css +1 -0
  546. package/dist/ui/components/toolbar-collapse.js +1 -2
  547. package/dist/ui/forms/FormShell.style.css +260 -311
  548. package/dist/ui/index.d.ts +2 -0
  549. package/dist/ui/index.js +1 -0
  550. package/dist/utils/index.d.ts +0 -1
  551. package/dist/utils/index.js +0 -1
  552. package/dist/validation/index.d.ts +1 -1
  553. package/dist/validation/index.js +1 -1
  554. package/dist/validation/schemas.d.ts +0 -19
  555. package/dist/validation/schemas.js +8 -19
  556. package/package.json +1 -1
  557. package/scripts/seed-cli.mjs +3 -6
@@ -3,6 +3,68 @@ import { z } from "zod";
3
3
  * 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
4
4
  * by schema instance and every zod wrapper returns a new one.
5
5
  */
6
+ /**
7
+ * The fields both coupon editors share, before either adds its own rules.
8
+ *
9
+ * Split out of `sellerCouponFormSchema` so the ADMIN editor can extend it.
10
+ * It could not before: that schema ends in `.superRefine`, which returns a
11
+ * ZodEffects with no `.extend()` — which is a large part of why the admin
12
+ * editor ended up declaring its own five-field `.passthrough()` stub locally
13
+ * and validating nothing at all.
14
+ */
15
+ export declare const couponFormBase: z.ZodObject<{
16
+ code: z.ZodString;
17
+ type: z.ZodEnum<["percentage", "fixed", "free_shipping"]>;
18
+ value: z.ZodEffects<z.ZodString, string, string>;
19
+ minPurchase: z.ZodEffects<z.ZodString, string, string>;
20
+ maxDiscount: z.ZodEffects<z.ZodString, string, string>;
21
+ totalLimit: z.ZodEffects<z.ZodString, string, string>;
22
+ perUserLimit: z.ZodEffects<z.ZodString, string, string>;
23
+ startDate: z.ZodString;
24
+ endDate: z.ZodString;
25
+ isActive: z.ZodBoolean;
26
+ applicableProducts: z.ZodArray<z.ZodString, "many">;
27
+ applicableCategories: z.ZodArray<z.ZodString, "many">;
28
+ }, "strip", z.ZodTypeAny, {
29
+ value: string;
30
+ code: string;
31
+ type: "fixed" | "percentage" | "free_shipping";
32
+ isActive: boolean;
33
+ endDate: string;
34
+ maxDiscount: string;
35
+ minPurchase: string;
36
+ applicableProducts: string[];
37
+ applicableCategories: string[];
38
+ totalLimit: string;
39
+ perUserLimit: string;
40
+ startDate: string;
41
+ }, {
42
+ value: string;
43
+ code: string;
44
+ type: "fixed" | "percentage" | "free_shipping";
45
+ isActive: boolean;
46
+ endDate: string;
47
+ maxDiscount: string;
48
+ minPurchase: string;
49
+ applicableProducts: string[];
50
+ applicableCategories: string[];
51
+ totalLimit: string;
52
+ perUserLimit: string;
53
+ startDate: string;
54
+ }>;
55
+ /**
56
+ * The cross-field rules both editors need. Shared for the same reason the
57
+ * fields are: a percentage over 100 is the store paying the customer whichever
58
+ * portal typed it.
59
+ */
60
+ export declare function refineCouponCommon(v: {
61
+ type: string;
62
+ value: string;
63
+ startDate: string;
64
+ endDate: string;
65
+ totalLimit: string;
66
+ perUserLimit: string;
67
+ }, ctx: z.RefinementCtx): void;
6
68
  export declare const sellerCouponFormSchema: z.ZodEffects<z.ZodObject<{
7
69
  code: z.ZodString;
8
70
  type: z.ZodEnum<["percentage", "fixed", "free_shipping"]>;
@@ -70,3 +132,155 @@ export declare const sellerCouponFormSchema: z.ZodEffects<z.ZodObject<{
70
132
  startDate: string;
71
133
  }>;
72
134
  export type SellerCouponFormValues = z.infer<typeof sellerCouponFormSchema>;
135
+ /**
136
+ * What `POST /api/store/coupons` accepts.
137
+ *
138
+ * The index signature is what lets it pass as a JSON body without a cast at the
139
+ * callsite — the named fields still constrain what may be set.
140
+ */
141
+ export interface SellerCouponPayload {
142
+ [key: string]: string | number | boolean | string[] | undefined;
143
+ code: string;
144
+ type: SellerCouponFormValues["type"];
145
+ value: number;
146
+ minPurchase?: number;
147
+ maxDiscount?: number;
148
+ totalLimit: number;
149
+ perUserLimit: number;
150
+ startDate: string;
151
+ endDate: string;
152
+ isActive: boolean;
153
+ applicableProducts?: string[];
154
+ applicableCategories?: string[];
155
+ }
156
+ /**
157
+ * The draft, as the route wants it.
158
+ *
159
+ * 🛑 One implementation because the conditions have to match the form's, and a
160
+ * per-callsite conversion is how they stopped matching: the create client
161
+ * correctly zeroed `value` for a free-shipping coupon and then sent
162
+ * `maxDiscount` for EVERY type — so a cap typed while the type was
163
+ * "percentage" survived a switch to fixed or free-shipping, invisibly, because
164
+ * the input that would have shown it was no longer rendered.
165
+ *
166
+ * The rule is now stated once, here, next to the `when` predicates it mirrors:
167
+ * a field the form hides is a field the payload omits.
168
+ */
169
+ export declare function couponDraftToPayload(draft: SellerCouponFormValues): SellerCouponPayload;
170
+ /**
171
+ * A coupon as an ADMIN edits it — the seller's fields plus the ones only the
172
+ * platform can set.
173
+ *
174
+ * `AdminCouponEditorView` declared its own schema locally: five fields, two of
175
+ * them `.passthrough()`, against nineteen rendered controls. It was passed to
176
+ * `<Form schema>` and never parsed, so none of the seventeen unlisted controls
177
+ * was checked by anything — `value` could be 500%, `endDate` could precede
178
+ * `startDate`, and `buyQuantity` could be zero.
179
+ *
180
+ * Extending the shared base rather than restating it is what keeps the two
181
+ * portals' rules from drifting; that they had already drifted is Root Cause
182
+ * #59's shape on the validation axis.
183
+ */
184
+ export declare const adminCouponFormSchema: z.ZodEffects<z.ZodObject<{
185
+ code: z.ZodString;
186
+ value: z.ZodEffects<z.ZodString, string, string>;
187
+ minPurchase: z.ZodEffects<z.ZodString, string, string>;
188
+ maxDiscount: z.ZodEffects<z.ZodString, string, string>;
189
+ totalLimit: z.ZodEffects<z.ZodString, string, string>;
190
+ perUserLimit: z.ZodEffects<z.ZodString, string, string>;
191
+ startDate: z.ZodString;
192
+ endDate: z.ZodString;
193
+ isActive: z.ZodBoolean;
194
+ applicableProducts: z.ZodArray<z.ZodString, "many">;
195
+ applicableCategories: z.ZodArray<z.ZodString, "many">;
196
+ } & {
197
+ type: z.ZodEnum<["percentage", "fixed", "free_shipping", "buy_x_get_y"]>;
198
+ name: z.ZodString;
199
+ description: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
200
+ buyQuantity: z.ZodEffects<z.ZodString, string, string>;
201
+ getQuantity: z.ZodEffects<z.ZodString, string, string>;
202
+ currentUsage: z.ZodOptional<z.ZodNumber>;
203
+ firstTimeUserOnly: z.ZodBoolean;
204
+ appliesToAuctions: z.ZodBoolean;
205
+ }, "strip", z.ZodTypeAny, {
206
+ value: string;
207
+ code: string;
208
+ type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
209
+ name: string;
210
+ isActive: boolean;
211
+ endDate: string;
212
+ firstTimeUserOnly: boolean;
213
+ maxDiscount: string;
214
+ minPurchase: string;
215
+ buyQuantity: string;
216
+ getQuantity: string;
217
+ applicableProducts: string[];
218
+ applicableCategories: string[];
219
+ totalLimit: string;
220
+ perUserLimit: string;
221
+ startDate: string;
222
+ appliesToAuctions: boolean;
223
+ description?: string | undefined;
224
+ currentUsage?: number | undefined;
225
+ }, {
226
+ value: string;
227
+ code: string;
228
+ type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
229
+ name: string;
230
+ isActive: boolean;
231
+ endDate: string;
232
+ firstTimeUserOnly: boolean;
233
+ maxDiscount: string;
234
+ minPurchase: string;
235
+ buyQuantity: string;
236
+ getQuantity: string;
237
+ applicableProducts: string[];
238
+ applicableCategories: string[];
239
+ totalLimit: string;
240
+ perUserLimit: string;
241
+ startDate: string;
242
+ appliesToAuctions: boolean;
243
+ description?: string | undefined;
244
+ currentUsage?: number | undefined;
245
+ }>, {
246
+ value: string;
247
+ code: string;
248
+ type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
249
+ name: string;
250
+ isActive: boolean;
251
+ endDate: string;
252
+ firstTimeUserOnly: boolean;
253
+ maxDiscount: string;
254
+ minPurchase: string;
255
+ buyQuantity: string;
256
+ getQuantity: string;
257
+ applicableProducts: string[];
258
+ applicableCategories: string[];
259
+ totalLimit: string;
260
+ perUserLimit: string;
261
+ startDate: string;
262
+ appliesToAuctions: boolean;
263
+ description?: string | undefined;
264
+ currentUsage?: number | undefined;
265
+ }, {
266
+ value: string;
267
+ code: string;
268
+ type: "fixed" | "percentage" | "free_shipping" | "buy_x_get_y";
269
+ name: string;
270
+ isActive: boolean;
271
+ endDate: string;
272
+ firstTimeUserOnly: boolean;
273
+ maxDiscount: string;
274
+ minPurchase: string;
275
+ buyQuantity: string;
276
+ getQuantity: string;
277
+ applicableProducts: string[];
278
+ applicableCategories: string[];
279
+ totalLimit: string;
280
+ perUserLimit: string;
281
+ startDate: string;
282
+ appliesToAuctions: boolean;
283
+ description?: string | undefined;
284
+ currentUsage?: number | undefined;
285
+ }>;
286
+ export type AdminCouponFormValues = z.infer<typeof adminCouponFormSchema>;
@@ -44,7 +44,16 @@ const numericString = (label) => z
44
44
  * 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
45
45
  * by schema instance and every zod wrapper returns a new one.
46
46
  */
47
- export const sellerCouponFormSchema = z
47
+ /**
48
+ * The fields both coupon editors share, before either adds its own rules.
49
+ *
50
+ * Split out of `sellerCouponFormSchema` so the ADMIN editor can extend it.
51
+ * It could not before: that schema ends in `.superRefine`, which returns a
52
+ * ZodEffects with no `.extend()` — which is a large part of why the admin
53
+ * editor ended up declaring its own five-field `.passthrough()` stub locally
54
+ * and validating nothing at all.
55
+ */
56
+ export const couponFormBase = z
48
57
  .object({
49
58
  code: annotate(z
50
59
  .string()
@@ -57,14 +66,26 @@ export const sellerCouponFormSchema = z
57
66
  type: annotate(z.enum(["percentage", "fixed", "free_shipping"]), {
58
67
  section: "basics", quick: true, order: 2, row: "pair",
59
68
  }),
69
+ /*
70
+ * `when` carries what the editor held as JSX conditionals, so a field the
71
+ * form hides is one the payload cannot carry — see `couponDraftToPayload`.
72
+ */
60
73
  value: annotate(numericString("The discount value"), {
61
74
  section: "basics", quick: true, order: 3, row: "pair",
75
+ when: (v) => v.type !== "free_shipping",
62
76
  }),
63
77
  minPurchase: annotate(numericString("Minimum purchase"), {
64
78
  section: "limits", sectionLabel: "Limits", order: 1, row: "pair",
65
79
  }),
80
+ /*
81
+ * A percentage cap is meaningless on a fixed or free-shipping coupon. The
82
+ * input was already hidden for those, and the value was SENT anyway — so a
83
+ * cap typed while the type was "percentage" persisted after switching to
84
+ * free shipping, invisibly.
85
+ */
66
86
  maxDiscount: annotate(numericString("Maximum discount"), {
67
87
  section: "limits", order: 2, row: "pair",
88
+ when: (v) => v.type === "percentage",
68
89
  }),
69
90
  totalLimit: annotate(numericString("Total uses"), {
70
91
  section: "limits", order: 3, row: "pair",
@@ -87,30 +108,141 @@ export const sellerCouponFormSchema = z
87
108
  applicableCategories: annotate(z.array(z.string()), {
88
109
  section: "scope", order: 2, row: "full", kind: "list",
89
110
  }),
111
+ });
112
+ /**
113
+ * The cross-field rules both editors need. Shared for the same reason the
114
+ * fields are: a percentage over 100 is the store paying the customer whichever
115
+ * portal typed it.
116
+ */
117
+ export function refineCouponCommon(v, ctx) {
118
+ {
119
+ const issue = (path, message) => ctx.addIssue({ code: z.ZodIssueCode.custom, path: [path], message });
120
+ // A discount value is required for everything except free shipping, and
121
+ // a percentage above 100 is not a discount — it is the store paying the
122
+ // customer. Nothing bounded this before.
123
+ if (v.type !== "free_shipping") {
124
+ const amount = Number(v.value);
125
+ if (v.value.trim() === "")
126
+ issue("value", "A discount value is required.");
127
+ else if (amount <= 0)
128
+ issue("value", "The discount must be greater than zero.");
129
+ else if (v.type === "percentage" && amount > 100) {
130
+ issue("value", "A percentage discount cannot exceed 100%.");
131
+ }
132
+ }
133
+ if (v.startDate && v.endDate && v.startDate > v.endDate) {
134
+ issue("endDate", "The end date must be after the start date.");
135
+ }
136
+ // A per-customer limit above the total makes the total unreachable — the
137
+ // coupon reads as more generous than it can ever be.
138
+ const total = Number(v.totalLimit);
139
+ const perUser = Number(v.perUserLimit);
140
+ if (v.totalLimit.trim() && v.perUserLimit.trim() && perUser > total) {
141
+ issue("perUserLimit", "Uses per customer cannot exceed the total uses.");
142
+ }
143
+ }
144
+ }
145
+ export const sellerCouponFormSchema = couponFormBase.superRefine(refineCouponCommon);
146
+ /**
147
+ * The draft, as the route wants it.
148
+ *
149
+ * 🛑 One implementation because the conditions have to match the form's, and a
150
+ * per-callsite conversion is how they stopped matching: the create client
151
+ * correctly zeroed `value` for a free-shipping coupon and then sent
152
+ * `maxDiscount` for EVERY type — so a cap typed while the type was
153
+ * "percentage" survived a switch to fixed or free-shipping, invisibly, because
154
+ * the input that would have shown it was no longer rendered.
155
+ *
156
+ * The rule is now stated once, here, next to the `when` predicates it mirrors:
157
+ * a field the form hides is a field the payload omits.
158
+ */
159
+ export function couponDraftToPayload(draft) {
160
+ const isPercentage = draft.type === "percentage";
161
+ const hasValue = draft.type !== "free_shipping";
162
+ return {
163
+ code: draft.code,
164
+ type: draft.type,
165
+ value: hasValue ? Number(draft.value) || 0 : 0,
166
+ minPurchase: draft.minPurchase ? Number(draft.minPurchase) : undefined,
167
+ maxDiscount: isPercentage && draft.maxDiscount ? Number(draft.maxDiscount) : undefined,
168
+ totalLimit: Number(draft.totalLimit) || 0,
169
+ perUserLimit: Number(draft.perUserLimit) || 0,
170
+ startDate: draft.startDate,
171
+ endDate: draft.endDate,
172
+ isActive: draft.isActive,
173
+ ...(draft.applicableProducts?.length ? { applicableProducts: draft.applicableProducts } : {}),
174
+ ...(draft.applicableCategories?.length
175
+ ? { applicableCategories: draft.applicableCategories }
176
+ : {}),
177
+ };
178
+ }
179
+ /**
180
+ * A coupon as an ADMIN edits it — the seller's fields plus the ones only the
181
+ * platform can set.
182
+ *
183
+ * `AdminCouponEditorView` declared its own schema locally: five fields, two of
184
+ * them `.passthrough()`, against nineteen rendered controls. It was passed to
185
+ * `<Form schema>` and never parsed, so none of the seventeen unlisted controls
186
+ * was checked by anything — `value` could be 500%, `endDate` could precede
187
+ * `startDate`, and `buyQuantity` could be zero.
188
+ *
189
+ * Extending the shared base rather than restating it is what keeps the two
190
+ * portals' rules from drifting; that they had already drifted is Root Cause
191
+ * #59's shape on the validation axis.
192
+ */
193
+ export const adminCouponFormSchema = couponFormBase
194
+ .extend({
195
+ /*
196
+ * Widened past the seller's three. Only the platform runs buy-x-get-y —
197
+ * a seller offering one would be spending another seller's stock.
198
+ */
199
+ type: annotate(z.enum(["percentage", "fixed", "free_shipping", "buy_x_get_y"]), {
200
+ section: "basics", quick: true, order: 2, row: "pair", label: "Coupon type",
201
+ }),
202
+ name: annotate(z.string().min(1, "Give the campaign a name.").max(120), {
203
+ section: "basics", quick: true, order: 4, row: "pair", label: "Campaign name",
204
+ }),
205
+ description: annotate(z.string().max(500).optional().or(z.literal("")), {
206
+ section: "basics", order: 5, row: "full", kind: "textarea",
207
+ }),
208
+ buyQuantity: annotate(numericString("Buy quantity"), {
209
+ section: "basics", order: 6, row: "pair", kind: "number",
210
+ when: (v) => v.type === "buy_x_get_y",
211
+ }),
212
+ getQuantity: annotate(numericString("Get quantity"), {
213
+ section: "basics", order: 7, row: "pair", kind: "number",
214
+ when: (v) => v.type === "buy_x_get_y",
215
+ }),
216
+ /*
217
+ * Written by orders, never by this form. `t3-mirror` renders it read-only
218
+ * instead of as a box an admin could set to whatever they liked — which is
219
+ * what "Current usage" was, `disabled` by an attribute a programmatic
220
+ * submit ignores.
221
+ */
222
+ currentUsage: annotate(z.number().int().min(0).optional(), {
223
+ section: "limits", order: 5, row: "pair", derived: true, tier: "t3-mirror",
224
+ label: "Current usage", help: "Updated by orders.",
225
+ }),
226
+ firstTimeUserOnly: annotate(z.boolean(), {
227
+ section: "scope", order: 3, row: "quarter", label: "First-time users only",
228
+ }),
229
+ appliesToAuctions: annotate(z.boolean(), {
230
+ section: "scope", order: 4, row: "quarter", label: "Applies to auctions",
231
+ }),
90
232
  })
91
233
  .superRefine((v, ctx) => {
92
- const issue = (path, message) => ctx.addIssue({ code: z.ZodIssueCode.custom, path: [path], message });
93
- // A discount value is required for everything except free shipping, and
94
- // a percentage above 100 is not a discount — it is the store paying the
95
- // customer. Nothing bounded this before.
96
- if (v.type !== "free_shipping") {
97
- const amount = Number(v.value);
98
- if (v.value.trim() === "")
99
- issue("value", "A discount value is required.");
100
- else if (amount <= 0)
101
- issue("value", "The discount must be greater than zero.");
102
- else if (v.type === "percentage" && amount > 100) {
103
- issue("value", "A percentage discount cannot exceed 100%.");
234
+ refineCouponCommon(v, ctx);
235
+ // A buy-x-get-y with a zero on either side is not an offer.
236
+ if (v.type === "buy_x_get_y") {
237
+ for (const key of ["buyQuantity", "getQuantity"]) {
238
+ const n = Number(v[key]);
239
+ if (v[key].trim() === "" || !Number.isFinite(n) || n < 1) {
240
+ ctx.addIssue({
241
+ code: z.ZodIssueCode.custom,
242
+ path: [key],
243
+ message: "Enter a whole number of one or more.",
244
+ });
245
+ }
104
246
  }
105
247
  }
106
- if (v.startDate && v.endDate && v.startDate > v.endDate) {
107
- issue("endDate", "The end date must be after the start date.");
108
- }
109
- // A per-customer limit above the total makes the total unreachable — the
110
- // coupon reads as more generous than it can ever be.
111
- const total = Number(v.totalLimit);
112
- const perUser = Number(v.perUserLimit);
113
- if (v.totalLimit.trim() && v.perUserLimit.trim() && perUser > total) {
114
- issue("perUserLimit", "Uses per customer cannot exceed the total uses.");
115
- }
116
248
  });
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import type { OfferBounds } from "../../../_internal/shared/features/offers/config";
2
3
  export declare const counterOfferFormSchema: z.ZodObject<{
3
4
  counterAmount: z.ZodNumber;
4
5
  sellerNote: z.ZodOptional<z.ZodString>;
@@ -13,16 +14,24 @@ export type CounterOfferFormValues = z.infer<typeof counterOfferFormSchema>;
13
14
  /**
14
15
  * Buyer-side Make-an-Offer form.
15
16
  *
16
- * A factory rather than a constant because both bounds depend on the listing:
17
- * the floor is `minOfferAmount(listedPrice, minOfferPercent)` and the ceiling is
18
- * the listed price itself. Both are re-checked server-side in `makeOffer` — this
19
- * exists so the buyer is told before submitting, using the SAME
20
- * `minOfferAmount()` the server uses, rather than a second rounding rule that
21
- * could disagree by a rupee.
17
+ * A factory rather than a constant because both bounds depend on the listing.
18
+ * It takes the already-resolved `OfferBounds` rather than recomputing them:
19
+ * `resolveOfferBounds()` is what `makeOffer` enforces, so anything this schema
20
+ * accepts, the server accepts. Deriving a second floor here is exactly how the
21
+ * forms came to advertise a 50% minimum the server rejected at 70 (see the
22
+ * offers config header).
23
+ *
24
+ * Three shapes, all from the same bounds object:
25
+ *
26
+ * - **Buy request** (`isBuyRequest`) — no cart on this type and no haggling
27
+ * opted in, so `min === max` and the only legal amount is the asking price.
28
+ * - **Offer, no cart** — floor to asking price *inclusive*: with no Add to Cart
29
+ * button, refusing a full-price offer would leave the buyer nowhere to go.
30
+ * - **Offer, cartable** — the original rule, ceiling exclusive of the price.
22
31
  */
23
32
  export declare function makeOfferFormSchema(opts: {
24
33
  listedPrice: number;
25
- minOffer: number;
34
+ bounds: OfferBounds;
26
35
  formatAmount: (n: number) => string;
27
36
  }): z.ZodObject<{
28
37
  offerAmount: z.ZodNumber;
@@ -31,21 +31,37 @@ export const counterOfferFormSchema = z.object({
31
31
  /**
32
32
  * Buyer-side Make-an-Offer form.
33
33
  *
34
- * A factory rather than a constant because both bounds depend on the listing:
35
- * the floor is `minOfferAmount(listedPrice, minOfferPercent)` and the ceiling is
36
- * the listed price itself. Both are re-checked server-side in `makeOffer` — this
37
- * exists so the buyer is told before submitting, using the SAME
38
- * `minOfferAmount()` the server uses, rather than a second rounding rule that
39
- * could disagree by a rupee.
34
+ * A factory rather than a constant because both bounds depend on the listing.
35
+ * It takes the already-resolved `OfferBounds` rather than recomputing them:
36
+ * `resolveOfferBounds()` is what `makeOffer` enforces, so anything this schema
37
+ * accepts, the server accepts. Deriving a second floor here is exactly how the
38
+ * forms came to advertise a 50% minimum the server rejected at 70 (see the
39
+ * offers config header).
40
+ *
41
+ * Three shapes, all from the same bounds object:
42
+ *
43
+ * - **Buy request** (`isBuyRequest`) — no cart on this type and no haggling
44
+ * opted in, so `min === max` and the only legal amount is the asking price.
45
+ * - **Offer, no cart** — floor to asking price *inclusive*: with no Add to Cart
46
+ * button, refusing a full-price offer would leave the buyer nowhere to go.
47
+ * - **Offer, cartable** — the original rule, ceiling exclusive of the price.
40
48
  */
41
49
  export function makeOfferFormSchema(opts) {
42
- const { listedPrice, minOffer, formatAmount } = opts;
50
+ const { listedPrice, bounds, formatAmount } = opts;
51
+ const amount = z.coerce
52
+ .number({ invalid_type_error: "Enter an offer amount." })
53
+ .positive("Offer amount must be greater than zero.");
54
+ const bounded = bounds.isBuyRequest
55
+ ? amount
56
+ .min(bounds.min, `This seller is not taking lower offers — the price is ${formatAmount(bounds.min)}.`)
57
+ .max(bounds.max, `This seller is not taking lower offers — the price is ${formatAmount(bounds.max)}.`)
58
+ : amount
59
+ .min(bounds.min, `Minimum offer is ${formatAmount(bounds.min)}.`)
60
+ .max(bounds.max, bounds.max >= listedPrice
61
+ ? `Your offer cannot exceed the asking price of ${formatAmount(listedPrice)}.`
62
+ : `Offer must be below the listed price of ${formatAmount(listedPrice)} — use Add to Cart to buy at that price.`);
43
63
  return z.object({
44
- offerAmount: z.coerce
45
- .number({ invalid_type_error: "Enter an offer amount." })
46
- .positive("Offer amount must be greater than zero.")
47
- .min(minOffer, `Minimum offer is ${formatAmount(minOffer)}.`)
48
- .max(listedPrice - 0.01, `Offer must be below the listed price of ${formatAmount(listedPrice)} — use Add to Cart to buy at that price.`),
64
+ offerAmount: bounded,
49
65
  buyerNote: z.string().max(300, "Keep your note under 300 characters.").optional(),
50
66
  });
51
67
  }
@@ -6,7 +6,7 @@ import { Button } from "../../ui/components/Button";
6
6
  import { IconButton } from "../../ui/components/IconButton";
7
7
  import { classNames } from "../../ui/style.helper";
8
8
  import { FORM_ACTION_META, FORM_ACTION_ID } from "../products/constants/action-defs";
9
- import { Div, Row, Span, Stack, Text } from "../../ui";
9
+ import { ActionRow, Div, Row, Span, Stack, Text } from "../../ui";
10
10
  /**
11
11
  * Carries the `schema` prop passed to `<FormShell>` down to any nested
12
12
  * `<SectionForm>` that doesn't declare its own `schema`/`SectionDef.schema` —
@@ -125,5 +125,5 @@ export function FormShell({ isOpen, onClose, title, breadcrumb, schema, isDirty
125
125
  return (_jsxs(FormSchemaContext.Provider, { value: schema, children: [_jsx(Div, { surface: "overlay-sm", className: "fixed inset-0 backdrop-blur-[2px]", style: { zIndex: "calc(var(--appkit-z-modal) - 1)" }, "aria-hidden": "true", onClick: attemptClose }), _jsxs(Div, { layout: "flex", ref: panelRef, role: "dialog", "aria-modal": "true", "aria-label": title, className: "fixed top-0 bottom-0 left-0 right-0 lg:left-[10%] lg:right-[10%] [flex-direction:column] bg-[var(--appkit-color-surface)]", shadow: "2xl", style: { zIndex: "var(--appkit-z-modal)" }, children: [_jsxs(Row, { gap: "sm", paddingX: "x-5", className: "flex-shrink-0 sticky top-0 z-10 border-b border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", padding: "y-sm", children: [previewMode ? (_jsxs(Button, { variant: "ghost", type: "button", onClick: () => setPreviewMode(false), "aria-label": "Back to edit", gap: "xs", rounded: "lg", textSize: "sm", textColor: "muted", className: "flex-shrink-0", children: [_jsx(ArrowLeft, { className: "w-4 h-4" }), _jsx(Span, { className: "hidden sm:inline", children: "Back to Edit" })] })) : (_jsx(IconButton, { type: "button", onClick: attemptClose, "aria-label": "Close", variant: "ghost", rounded: "lg", className: "text-[var(--appkit-color-text-muted)] flex-shrink-0", children: _jsx(X, { className: "w-5 h-5" }) })), _jsxs(Div, { className: "flex-1 min-w-0", children: [breadcrumb && (_jsx(Text, { className: "text-[var(--appkit-color-text-muted)] truncate mb-0.5", size: "xs", children: breadcrumb })), _jsx(Text, { className: "text-[var(--appkit-color-text)] truncate", size: "sm", weight: "semibold", children: previewMode ? `Preview — ${title}` : title })] }), _jsx(Row, { gap: "xs", className: "flex-shrink-0", children: previewMode ? null : (_jsxs(_Fragment, { children: [previewSlot && (_jsxs(Button, { variant: "outline", type: "button", onClick: () => setPreviewMode(true), gap: "xs", rounded: "lg", paddingX: "sm", textSize: "sm", textColor: "muted", children: [_jsx(Eye, { className: "w-4 h-4" }), _jsx(Span, { className: "hidden sm:inline", children: "Preview" })] })), onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsx(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: publishLabel }))] })) })] }), _jsxs(Div, { layout: "flex", className: `flex-1 ${__O.hidden}`, children: [sections && sections.length > 0 && !previewMode && (_jsx("nav", { "aria-label": "Form sections", className: "hidden lg:flex flex-col flex-shrink-0 w-48 border-r border-[var(--appkit-color-border)] py-[var(--appkit-space-4)] px-[var(--appkit-space-3)] gap-[var(--appkit-space-1)] overflow-y-auto", children: sections.map((sec) => (_jsx(Button, { variant: "ghost", type: "button", onClick: () => scrollToSection(sec.id), rounded: "lg", paddingX: "sm", paddingY: "xs", textSize: "sm", textColor: "muted", justify: "start", className: "text-left", children: sec.label }, sec.id))) })), sections && sections.length > 0 && !previewMode && (_jsx(Row, { gap: "px", className: `lg:hidden fixed top-[var(--form-shell-topbar-h,57px)] left-0 right-0 z-10 ${__O.xAuto} px-[1.25rem] bg-[var(--appkit-color-surface)] border-b border-[var(--appkit-color-border)]`, padding: "y-xs", children: sections.map((sec) => (_jsx(Button, { variant: "outline", type: "button", onClick: () => scrollToSection(sec.id), rounded: "full", paddingX: "sm", paddingY: "xs", textSize: "xs", textColor: "muted", className: "flex-shrink-0 hover:border-primary hover:text-primary whitespace-nowrap", children: sec.label }, sec.id))) })), _jsx(Div, { ref: bodyRef, className: classNames("flex-1 overflow-y-auto", sections && sections.length > 0 && !previewMode ? "pt-[var(--appkit-space-0)] lg:pt-[var(--appkit-space-0)]" : ""), children: previewMode && previewSlot ? (_jsxs(_Fragment, { children: [_jsxs(Row, { textSize: "sm", gap: "xs", className: "sticky top-0 z-10 bg-[var(--appkit-color-warning-surface)] border-b border-[var(--appkit-color-warning)] text-[var(--appkit-color-warning-text,var(--appkit-color-warning))]", paddingY: "y-xs", paddingX: "x-md", children: [_jsx(Eye, { className: "w-4 h-4 flex-shrink-0" }), _jsx(Span, { children: "Preview \u2014 not visible to buyers until published" })] }), _jsx(Div, { padding: "y-md", children: previewSlot() })] })) : splitPreview && previewSlot ? (
126
126
  // S-STORE-3-D — desktop 60/40 split: form left, preview right.
127
127
  // Below `lg`, falls back to single-column form (preview-as-modal via existing toggle).
128
- _jsxs(Div, { className: "lg:grid lg:grid-cols-[3fr_2fr] lg:gap-[1.5rem] lg:px-[1.5rem] lg:py-[1.5rem] lg:max-w-[1400px] lg:mx-auto", children: [_jsx(Div, { className: "max-w-3xl mx-auto px-[1.25rem] sm:px-[1.5rem] lg:max-w-none lg:px-[0] lg:py-[0]", padding: "y-lg", children: children }), _jsxs(Div, { className: `hidden lg:block sticky lg:top-4 lg:self-start lg:max-h-[calc(100vh-6rem)] ${__O.yAuto} border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] ${__P.p4}`, rounded: "lg", children: [_jsxs(Row, { textWeight: "semibold", textSize: "xs", gap: "xs", className: "mb-3 uppercase tracking-wide text-[var(--appkit-color-text-muted)]", children: [_jsx(Eye, { className: "w-3.5 h-3.5" }), _jsx(Span, { children: "Live preview" })] }), previewSlot()] })] })) : (_jsx(Div, { className: "max-w-3xl mx-auto px-[1.25rem] sm:px-[1.5rem]", padding: "y-lg", children: children })) })] }), !previewMode && renderBottomBar ? (renderBottomBar()) : !previewMode && (onSaveDraft || onPublish) ? (_jsxs(Stack, { gap: "none", className: "flex-shrink-0 sticky bottom-0 z-10 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", children: [footerTopSlot && (_jsx(Div, { paddingX: "x-5", padding: "t-sm", children: footerTopSlot })), _jsxs(Row, { justify: "between", paddingX: "x-5", padding: "y-sm", style: { paddingBottom: "calc(var(--appkit-space-3) + var(--keyboard-inset-height, 0px))" }, children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: attemptClose, disabled: isLoading, children: FORM_ACTION_META[FORM_ACTION_ID.DISCARD].label }), _jsxs(Row, { gap: "xs", children: [onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsxs(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: [publishLabel, " \u2192"] }))] })] })] })) : null] }), showUnsaved && (_jsxs(_Fragment, { children: [_jsx(Div, { surface: "overlay-lg", className: "fixed inset-0", style: { zIndex: "var(--appkit-z-confirm)" }, onClick: () => setShowUnsaved(false) }), _jsxs(Div, { className: "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[90vw] max-w-sm bg-[var(--appkit-color-surface)]", shadow: "2xl", rounded: "xl", padding: "lg", style: { zIndex: "var(--appkit-z-confirm)" }, children: [_jsxs(Row, { gap: "sm", align: "start", className: "mb-4", children: [_jsx(Span, { layout: "flex-center", className: "flex-shrink-0 w-10 h-10 bg-[var(--appkit-color-warning-surface)]", rounded: "full", children: _jsx(AlertTriangle, { className: "w-5 h-5 text-[var(--appkit-color-warning)]" }) }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { className: "text-[var(--appkit-color-text)]", weight: "semibold", children: "Unsaved changes" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "You have unsaved changes. Leave without saving?" })] })] }), _jsxs(Row, { gap: "xs", justify: "end", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setShowUnsaved(false), children: "Stay" }), _jsx(Button, { variant: "danger", size: "sm", onClick: () => { setShowUnsaved(false); onClose(); }, children: "Leave" })] })] })] }))] }));
128
+ _jsxs(Div, { className: "lg:grid lg:grid-cols-[3fr_2fr] lg:gap-[1.5rem] lg:px-[1.5rem] lg:py-[1.5rem] lg:max-w-[1400px] lg:mx-auto", children: [_jsx(Div, { className: "max-w-3xl mx-auto px-[1.25rem] sm:px-[1.5rem] lg:max-w-none lg:px-[0] lg:py-[0]", padding: "y-lg", children: children }), _jsxs(Div, { className: `hidden lg:block sticky lg:top-4 lg:self-start lg:max-h-[calc(100vh-6rem)] ${__O.yAuto} border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] ${__P.p4}`, rounded: "lg", children: [_jsxs(Row, { textWeight: "semibold", textSize: "xs", gap: "xs", className: "mb-3 uppercase tracking-wide text-[var(--appkit-color-text-muted)]", children: [_jsx(Eye, { className: "w-3.5 h-3.5" }), _jsx(Span, { children: "Live preview" })] }), previewSlot()] })] })) : (_jsx(Div, { className: "max-w-3xl mx-auto px-[1.25rem] sm:px-[1.5rem]", padding: "y-lg", children: children })) })] }), !previewMode && renderBottomBar ? (renderBottomBar()) : !previewMode && (onSaveDraft || onPublish) ? (_jsxs(Stack, { gap: "none", className: "flex-shrink-0 sticky bottom-0 z-10 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", children: [footerTopSlot && (_jsx(Div, { paddingX: "x-5", padding: "t-sm", children: footerTopSlot })), _jsxs(ActionRow, { align: "end", paddingX: "x-5", padding: "y-sm", style: { paddingBottom: "calc(var(--appkit-space-3) + var(--keyboard-inset-height, 0px))" }, anchor: _jsx(Button, { variant: "ghost", size: "sm", onClick: attemptClose, disabled: isLoading, children: FORM_ACTION_META[FORM_ACTION_ID.DISCARD].label }), children: [onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsxs(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: [publishLabel, " \u2192"] }))] })] })) : null] }), showUnsaved && (_jsxs(_Fragment, { children: [_jsx(Div, { surface: "overlay-lg", className: "fixed inset-0", style: { zIndex: "var(--appkit-z-confirm)" }, onClick: () => setShowUnsaved(false) }), _jsxs(Div, { className: "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[90vw] max-w-sm bg-[var(--appkit-color-surface)]", shadow: "2xl", rounded: "xl", padding: "lg", style: { zIndex: "var(--appkit-z-confirm)" }, children: [_jsxs(Row, { gap: "sm", align: "start", className: "mb-4", children: [_jsx(Span, { layout: "flex-center", className: "flex-shrink-0 w-10 h-10 bg-[var(--appkit-color-warning-surface)]", rounded: "full", children: _jsx(AlertTriangle, { className: "w-5 h-5 text-[var(--appkit-color-warning)]" }) }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { className: "text-[var(--appkit-color-text)]", weight: "semibold", children: "Unsaved changes" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "You have unsaved changes. Leave without saving?" })] })] }), _jsxs(Row, { gap: "xs", justify: "end", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setShowUnsaved(false), children: "Stay" }), _jsx(Button, { variant: "danger", size: "sm", onClick: () => { setShowUnsaved(false); onClose(); }, children: "Leave" })] })] })] }))] }));
129
129
  }
@@ -6,7 +6,7 @@ import { Button } from "../../ui/components/Button";
6
6
  import { IconButton } from "../../ui/components/IconButton";
7
7
  import { FormField } from "../../ui/components/FormField";
8
8
  import { Toggle } from "../../ui/components/Toggle";
9
- import { Div, Form, Row, Stack, Text } from "../../ui";
9
+ import { ActionRow, Div, Form, Row, Stack, Text } from "../../ui";
10
10
  import { FormShellContext, FormErrorSummary } from "../../ui/forms";
11
11
  import { useHandMode } from "../../_internal/client/hand-mode";
12
12
  function initValues(fields, defaults = {}) {
@@ -203,5 +203,5 @@ export function QuickFormDrawer({ isOpen, onClose, title, fields, defaultValues,
203
203
  : field.type === "select"
204
204
  ? "select"
205
205
  : "text", value: String(value ?? ""), onChange: (v) => set(field.name, field.type === "number" ? Number(v) : v), options: field.options, placeholder: field.placeholder, disabled: busy, error: errors[field.name] }), field.helperText && !errors[field.name] && (_jsx(Text, { className: "mt-1 text-[var(--appkit-color-text-muted)]", size: "xs", children: field.helperText }))] }, field.name));
206
- }), renderExtra?.(values, set)] }), _jsxs(Div, { className: "flex-shrink-0 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-bg)]", children: [_jsx(Div, { paddingX: "x-md", padding: "t-sm", children: _jsx(FormErrorSummary, {}) }), _jsxs(Row, { padding: "md", align: "center", justify: "between", gap: "sm", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: handleClose, disabled: busy, children: cancelLabel }), _jsxs(Button, { variant: "primary", size: "sm", onClick: () => void handleSubmit(), disabled: busy, isLoading: busy, children: [submitLabel, " \u2192"] })] })] })] })] }) }));
206
+ }), renderExtra?.(values, set)] }), _jsxs(Div, { className: "flex-shrink-0 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-bg)]", children: [_jsx(Div, { paddingX: "x-md", padding: "t-sm", children: _jsx(FormErrorSummary, {}) }), _jsxs(ActionRow, { padding: "md", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: handleClose, disabled: busy, children: cancelLabel }), _jsxs(Button, { variant: "primary", size: "sm", onClick: () => void handleSubmit(), disabled: busy, isLoading: busy, children: [submitLabel, " \u2192"] })] })] })] })] }) }));
207
207
  }
@@ -110,6 +110,14 @@ export interface SectionFormProps<T extends object = Record<string, JsonValue>>
110
110
  export declare function orderSections<T extends object>(sections: SectionDef<T>[]): SectionDef<T>[];
111
111
  /** `fieldName -> index into the ORDERED section list`. */
112
112
  export declare function buildFieldToSectionIndex<T extends object>(ordered: SectionDef<T>[]): Record<string, number>;
113
+ export interface UseSectionFormNavOptions {
114
+ /**
115
+ * `"{portal}:{surface}"` — persists this form's open set to the user's
116
+ * profile. Omit for in-memory-only, which is the default and what every
117
+ * pre-existing call site gets.
118
+ */
119
+ scope?: string;
120
+ }
113
121
  export interface UseSectionFormNavResult<T extends object> {
114
122
  /** Sections in render order — required first. */
115
123
  ordered: SectionDef<T>[];
@@ -126,8 +134,18 @@ export interface UseSectionFormNavResult<T extends object> {
126
134
  * `fieldToSectionIndex` into `useFormShellState(schema, nav)` and `openIds`
127
135
  * back into `<SectionForm>`.
128
136
  */
129
- export declare function useSectionFormNav<T extends object = Record<string, JsonValue>>(sections: SectionDef<T>[], values?: T): UseSectionFormNavResult<T>;
137
+ export declare function useSectionFormNav<T extends object = Record<string, JsonValue>>(sections: SectionDef<T>[], values?: T, opts?: UseSectionFormNavOptions): UseSectionFormNavResult<T>;
130
138
  /** DOM id for a section panel — kept in one place so nav and render agree. */
131
139
  export declare function sectionAnchorId(id: string): string;
140
+ /**
141
+ * Scroll a section into view and focus the first invalid control inside it.
142
+ *
143
+ * Deliberately module-level and shared by `goToSection` and `SectionForm`'s own
144
+ * submit handler: the deferred frame is the load-bearing part and is easy to
145
+ * drop when copying. The panel must MOUNT before it can be scrolled to —
146
+ * expanding is a state update, so without the deferral the scroll lands on a
147
+ * zero-height collapsed header and the offending field stays off-screen.
148
+ */
149
+ export declare function scrollToSection(id: string): void;
132
150
  export declare function SectionForm<T extends object = Record<string, JsonValue>>({ sections, values, onChange, onSubmit, submitLabel, isLoading, schema, openIds: controlledOpenIds, onOpenChange, expandMode, hideActions, destructiveAction, onValidationChange, onCancel, cancelLabel, bottomBar, }: SectionFormProps<T>): import("react").JSX.Element;
133
151
  export default SectionForm;