@mohasinac/appkit 4.53.0 → 4.53.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.
Files changed (500) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/scaffolds/AppShell.js +1 -1
  3. package/dist/_internal/server/features/auctions/og.d.ts +3 -1
  4. package/dist/_internal/server/features/auctions/og.js +3 -1
  5. package/dist/_internal/server/features/bundles/actions.js +1 -1
  6. package/dist/_internal/server/features/business-documents/download.d.ts +41 -0
  7. package/dist/_internal/server/features/business-documents/download.js +91 -0
  8. package/dist/_internal/server/features/categories/adapters.d.ts +1 -1
  9. package/dist/_internal/server/features/categories/adapters.js +10 -0
  10. package/dist/_internal/server/features/checkout/actions.d.ts +14 -0
  11. package/dist/_internal/server/features/checkout/actions.js +106 -12
  12. package/dist/_internal/server/features/checkout/bundle-expansion.js +17 -0
  13. package/dist/_internal/server/features/checkout/data.d.ts +22 -0
  14. package/dist/_internal/server/features/checkout/group-rule-revalidation.d.ts +34 -0
  15. package/dist/_internal/server/features/checkout/group-rule-revalidation.js +124 -0
  16. package/dist/_internal/server/features/checkout/supplier-identity.d.ts +55 -0
  17. package/dist/_internal/server/features/checkout/supplier-identity.js +81 -0
  18. package/dist/_internal/server/features/classified/metadata.js +1 -1
  19. package/dist/_internal/server/features/classified/og.d.ts +3 -1
  20. package/dist/_internal/server/features/classified/og.js +3 -1
  21. package/dist/_internal/server/features/digital-code/metadata.js +1 -1
  22. package/dist/_internal/server/features/digital-code/og.d.ts +3 -1
  23. package/dist/_internal/server/features/digital-code/og.js +3 -1
  24. package/dist/_internal/server/features/digital-code/pool.d.ts +19 -4
  25. package/dist/_internal/server/features/digital-code/pool.js +19 -4
  26. package/dist/_internal/server/features/live/metadata.js +1 -1
  27. package/dist/_internal/server/features/live/og.d.ts +3 -1
  28. package/dist/_internal/server/features/live/og.js +3 -1
  29. package/dist/_internal/server/features/messages/actions.js +1 -1
  30. package/dist/_internal/server/features/parts/og.js +1 -1
  31. package/dist/_internal/server/features/pre-orders/og.d.ts +3 -1
  32. package/dist/_internal/server/features/pre-orders/og.js +3 -1
  33. package/dist/_internal/server/features/price-index/search.d.ts +18 -0
  34. package/dist/_internal/server/features/price-index/search.js +47 -7
  35. package/dist/_internal/server/features/prize-draws/og.d.ts +3 -1
  36. package/dist/_internal/server/features/prize-draws/og.js +3 -1
  37. package/dist/_internal/server/features/products/group-members.d.ts +26 -0
  38. package/dist/_internal/server/features/products/group-members.js +7 -1
  39. package/dist/_internal/server/features/products/og.d.ts +3 -1
  40. package/dist/_internal/server/features/products/og.js +3 -1
  41. package/dist/_internal/server/features/search/scoped-sources.d.ts +26 -0
  42. package/dist/_internal/server/features/search/scoped-sources.js +252 -0
  43. package/dist/_internal/server/features/search/search-everything.d.ts +57 -0
  44. package/dist/_internal/server/features/search/search-everything.js +70 -20
  45. package/dist/_internal/server/features/seo/sitemap.js +6 -0
  46. package/dist/_internal/server/features/shared/listing-adapters.js +4 -2
  47. package/dist/_internal/server/features/sticker-trace/adapters.d.ts +11 -0
  48. package/dist/_internal/server/features/sticker-trace/adapters.js +1 -0
  49. package/dist/_internal/server/features/sticker-trace/promote-to-listings.d.ts +26 -0
  50. package/dist/_internal/server/features/sticker-trace/promote-to-listings.js +264 -0
  51. package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +3 -1
  52. package/dist/_internal/server/features/sticker-trace/sheet-actions.js +32 -0
  53. package/dist/_internal/server/features/sticker-trace/storage.d.ts +20 -1
  54. package/dist/_internal/server/features/sticker-trace/storage.js +20 -1
  55. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  56. package/dist/_internal/server/features/stores/adapters.js +16 -0
  57. package/dist/_internal/server/features/stores/index.d.ts +1 -0
  58. package/dist/_internal/server/features/stores/index.js +1 -0
  59. package/dist/_internal/server/features/stores/tabs.d.ts +25 -0
  60. package/dist/_internal/server/features/stores/tabs.js +122 -0
  61. package/dist/_internal/shared/checkout/rules/_defaults.js +0 -2
  62. package/dist/_internal/shared/checkout/rules/_limits.d.ts +14 -1
  63. package/dist/_internal/shared/checkout/rules/_limits.js +14 -1
  64. package/dist/_internal/shared/checkout/rules/_registry.js +2 -0
  65. package/dist/_internal/shared/checkout/rules/auction.rule.js +9 -1
  66. package/dist/_internal/shared/checkout/rules/bundle.rule.js +13 -0
  67. package/dist/_internal/shared/checkout/rules/index.d.ts +2 -0
  68. package/dist/_internal/shared/checkout/rules/index.js +9 -0
  69. package/dist/_internal/shared/checkout/rules/offer.rule.js +0 -1
  70. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +26 -0
  71. package/dist/_internal/shared/checkout/rules/payment-gate.js +133 -0
  72. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +29 -8
  73. package/dist/_internal/shared/checkout/rules/spares.rule.d.ts +16 -0
  74. package/dist/_internal/shared/checkout/rules/spares.rule.js +5 -0
  75. package/dist/_internal/shared/checkout/rules/types.d.ts +26 -2
  76. package/dist/_internal/shared/config/schema.d.ts +122 -0
  77. package/dist/_internal/shared/features/cart/schema.js +3 -2
  78. package/dist/_internal/shared/features/products/group-rules.d.ts +75 -0
  79. package/dist/_internal/shared/features/products/group-rules.js +142 -0
  80. package/dist/_internal/shared/listing-types/_registry.d.ts +24 -0
  81. package/dist/_internal/shared/listing-types/_registry.js +39 -1
  82. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
  83. package/dist/_internal/shared/listing-types/art/config.js +2 -0
  84. package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
  85. package/dist/_internal/shared/listing-types/auction/config.js +2 -0
  86. package/dist/_internal/shared/listing-types/availability.js +48 -0
  87. package/dist/_internal/shared/listing-types/capabilities.js +19 -0
  88. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
  89. package/dist/_internal/shared/listing-types/classified/config.js +2 -0
  90. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
  91. package/dist/_internal/shared/listing-types/digital-code/config.js +2 -0
  92. package/dist/_internal/shared/listing-types/feature-flags.js +1 -0
  93. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
  94. package/dist/_internal/shared/listing-types/live/config.js +2 -0
  95. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
  96. package/dist/_internal/shared/listing-types/pre-order/config.js +2 -0
  97. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
  98. package/dist/_internal/shared/listing-types/prize-draw/config.js +2 -0
  99. package/dist/_internal/shared/listing-types/spares/config.d.ts +74 -0
  100. package/dist/_internal/shared/listing-types/spares/config.js +60 -0
  101. package/dist/_internal/shared/listing-types/spares/ctas.d.ts +1 -0
  102. package/dist/_internal/shared/listing-types/spares/ctas.js +4 -0
  103. package/dist/_internal/shared/listing-types/spares/og.js +1 -0
  104. package/dist/_internal/shared/listing-types/spares/schema.d.ts +2 -0
  105. package/dist/_internal/shared/listing-types/spares/schema.js +3 -0
  106. package/dist/_internal/shared/listing-types/spares/seed-factory.d.ts +1 -0
  107. package/dist/_internal/shared/listing-types/spares/seed-factory.js +1 -0
  108. package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
  109. package/dist/_internal/shared/listing-types/standard/config.js +2 -0
  110. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
  111. package/dist/_internal/shared/listing-types/stickers/config.js +2 -0
  112. package/dist/_internal/shared/search/match.d.ts +11 -0
  113. package/dist/_internal/shared/search/match.js +2 -1
  114. package/dist/_internal/shared/search/to-groups.d.ts +52 -0
  115. package/dist/_internal/shared/search/to-groups.js +141 -0
  116. package/dist/client.d.ts +8 -2
  117. package/dist/client.js +4 -1
  118. package/dist/constants/api-endpoints.d.ts +39 -15
  119. package/dist/constants/api-endpoints.js +28 -5
  120. package/dist/constants/cache-invalidation.js +3 -1
  121. package/dist/constants/field-names.d.ts +6 -0
  122. package/dist/constants/field-names.js +6 -0
  123. package/dist/features/about/components/PolicyPageView.d.ts +22 -2
  124. package/dist/features/about/components/PolicyPageView.js +14 -2
  125. package/dist/features/about/components/PublicProfileView.js +2 -1
  126. package/dist/features/about/components/ShippingPolicyView.js +42 -2
  127. package/dist/features/account/components/NotificationBell.js +1 -1
  128. package/dist/features/account/hooks/useProfileStats.js +5 -1
  129. package/dist/features/addresses/repository/addresses.repository.d.ts +16 -0
  130. package/dist/features/addresses/repository/addresses.repository.js +21 -0
  131. package/dist/features/admin/actions/admin-actions.js +16 -1
  132. package/dist/features/admin/components/AdminCategoryEditorView.js +19 -2
  133. package/dist/features/admin/components/AdminNavigationView.js +1 -1
  134. package/dist/features/admin/components/AdminPageHeader.js +1 -1
  135. package/dist/features/admin/components/AdminProductEditorView.js +17 -2
  136. package/dist/features/admin/components/AdminSidebar.js +1 -1
  137. package/dist/features/admin/components/AdminSiteSettingsView.js +39 -8
  138. package/dist/features/admin/components/AdminSparesView.d.ts +12 -0
  139. package/dist/features/admin/components/AdminSparesView.js +30 -0
  140. package/dist/features/admin/components/AdminUsersView.js +9 -7
  141. package/dist/features/admin/components/index.d.ts +2 -0
  142. package/dist/features/admin/components/index.js +1 -0
  143. package/dist/features/admin/components/sections/adminSectionsTypes.js +7 -0
  144. package/dist/features/admin/constants/filter-tabs.d.ts +3 -0
  145. package/dist/features/admin/constants/filter-tabs.js +1 -0
  146. package/dist/features/admin/schemas/firestore.d.ts +26 -2
  147. package/dist/features/auctions/components/AuctionDetailPageView.js +4 -11
  148. package/dist/features/auth/repository/user.repository.d.ts +13 -0
  149. package/dist/features/auth/repository/user.repository.js +28 -0
  150. package/dist/features/auth/schemas/firestore.d.ts +2 -0
  151. package/dist/features/auth/schemas/firestore.js +2 -0
  152. package/dist/features/business-documents/repository/business-documents.repository.d.ts +58 -0
  153. package/dist/features/business-documents/repository/business-documents.repository.js +54 -0
  154. package/dist/features/business-documents/schemas/firestore.d.ts +105 -0
  155. package/dist/features/business-documents/schemas/firestore.js +75 -0
  156. package/dist/features/cart/actions/cart-actions.js +83 -6
  157. package/dist/features/cart/repository/cart.repository.js +32 -4
  158. package/dist/features/cart/schemas/firestore.d.ts +20 -0
  159. package/dist/features/cart/schemas/index.d.ts +2 -2
  160. package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +1 -1
  161. package/dist/features/categories/api/[id]/price-guidance/route.d.ts +42 -0
  162. package/dist/features/categories/api/[id]/price-guidance/route.js +113 -0
  163. package/dist/features/categories/components/BrandDetailPageView.js +19 -3
  164. package/dist/features/categories/components/BrandDetailTabs.js +10 -0
  165. package/dist/features/categories/components/CategoriesIndexListing.js +23 -8
  166. package/dist/features/categories/components/CategoryDetailPageView.js +141 -14
  167. package/dist/features/categories/components/CategoryDetailTabs.js +12 -0
  168. package/dist/features/categories/components/CategoryGrid.js +10 -1
  169. package/dist/features/categories/components/PriceGuidanceHint.d.ts +29 -0
  170. package/dist/features/categories/components/PriceGuidanceHint.js +61 -0
  171. package/dist/features/categories/components/SubcategoryCardRow.d.ts +27 -0
  172. package/dist/features/categories/components/SubcategoryCardRow.js +98 -0
  173. package/dist/features/categories/constants/category-tabs.d.ts +20 -25
  174. package/dist/features/categories/constants/category-tabs.js +22 -39
  175. package/dist/features/categories/repository/categories.repository.d.ts +12 -0
  176. package/dist/features/categories/repository/categories.repository.js +20 -0
  177. package/dist/features/categories/schemas/firestore.d.ts +22 -1
  178. package/dist/features/categories/schemas/firestore.js +10 -0
  179. package/dist/features/categories/schemas/index.d.ts +6 -0
  180. package/dist/features/categories/schemas/index.js +2 -0
  181. package/dist/features/categories/types/index.d.ts +8 -0
  182. package/dist/features/categories/utils/taxonomy-visual.d.ts +16 -3
  183. package/dist/features/categories/utils/taxonomy-visual.js +26 -10
  184. package/dist/features/classified/components/ClassifiedDetailPageView.js +4 -9
  185. package/dist/features/contact/components/ContactPageView.d.ts +33 -1
  186. package/dist/features/contact/components/ContactPageView.js +58 -28
  187. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +4 -9
  188. package/dist/features/grouped/components/GroupedListingDetailView.js +9 -1
  189. package/dist/features/grouped/schemas/firestore.d.ts +5 -0
  190. package/dist/features/homepage/actions/homepage-section-actions.d.ts +3 -3
  191. package/dist/features/homepage/components/CollectionCardsSection.d.ts +28 -6
  192. package/dist/features/homepage/components/CollectionCardsSection.js +43 -8
  193. package/dist/features/homepage/components/HowItWorksSection.d.ts +23 -6
  194. package/dist/features/homepage/components/HowItWorksSection.js +4 -4
  195. package/dist/features/homepage/components/PromoGrid.d.ts +31 -2
  196. package/dist/features/homepage/components/PromoGrid.js +12 -3
  197. package/dist/features/homepage/components/TestimonialsCarousel.d.ts +34 -2
  198. package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
  199. package/dist/features/homepage/components/index.d.ts +0 -20
  200. package/dist/features/homepage/components/index.js +0 -11
  201. package/dist/features/homepage/index.d.ts +0 -2
  202. package/dist/features/homepage/index.js +0 -2
  203. package/dist/features/homepage/lib/section-renderer.d.ts +9 -0
  204. package/dist/features/homepage/lib/section-renderer.js +202 -58
  205. package/dist/features/homepage/repository/homepage-sections.repository.d.ts +35 -3
  206. package/dist/features/homepage/repository/homepage-sections.repository.js +58 -8
  207. package/dist/features/homepage/schemas/firestore.d.ts +106 -3
  208. package/dist/features/homepage/schemas/firestore.js +32 -2
  209. package/dist/features/homepage/schemas/index.d.ts +36 -7
  210. package/dist/features/homepage/schemas/index.js +39 -27
  211. package/dist/features/homepage/server.d.ts +0 -3
  212. package/dist/features/homepage/server.js +0 -3
  213. package/dist/features/homepage/types/index.d.ts +0 -47
  214. package/dist/features/homepage/types/index.js +49 -0
  215. package/dist/features/layout/AppLayoutShell.js +1 -1
  216. package/dist/features/layout/BottomNavItem.js +1 -1
  217. package/dist/features/layout/BottomSheet.js +1 -1
  218. package/dist/features/layout/TitleBarLayout.js +1 -1
  219. package/dist/features/live/components/LiveItemDetailPageView.js +4 -9
  220. package/dist/features/media/hooks/useMedia.js +17 -0
  221. package/dist/features/media/repository/media-assets.repository.d.ts +46 -0
  222. package/dist/features/media/repository/media-assets.repository.js +31 -0
  223. package/dist/features/media/trust-signals.d.ts +85 -0
  224. package/dist/features/media/trust-signals.js +126 -0
  225. package/dist/features/parts/components/PartDetailPageView.d.ts +14 -1
  226. package/dist/features/parts/components/PartDetailPageView.js +2 -2
  227. package/dist/features/parts/components/PartsIndexPageView.d.ts +11 -2
  228. package/dist/features/parts/components/PartsIndexPageView.js +2 -2
  229. package/dist/features/parts/components/PartsSearchBox.d.ts +9 -0
  230. package/dist/features/parts/components/PartsSearchBox.js +57 -0
  231. package/dist/features/parts/schemas/firestore.d.ts +149 -3
  232. package/dist/features/parts/schemas/firestore.js +184 -0
  233. package/dist/features/payments/repository/payout.repository.d.ts +15 -0
  234. package/dist/features/payments/repository/payout.repository.js +21 -0
  235. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -11
  236. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +1 -1
  237. package/dist/features/price-index/components/PriceIndexToolView.d.ts +3 -1
  238. package/dist/features/price-index/components/PriceIndexToolView.js +92 -13
  239. package/dist/features/products/components/CompareOverlay.d.ts +18 -1
  240. package/dist/features/products/components/CompareOverlay.js +21 -2
  241. package/dist/features/products/components/CustomSectionTabContent.d.ts +31 -0
  242. package/dist/features/products/components/CustomSectionTabContent.js +29 -3
  243. package/dist/features/products/components/GroupMemberPicker.d.ts +19 -1
  244. package/dist/features/products/components/GroupMemberPicker.js +46 -8
  245. package/dist/features/products/components/GroupSettingsPanel.d.ts +11 -1
  246. package/dist/features/products/components/GroupSettingsPanel.js +91 -3
  247. package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
  248. package/dist/features/products/components/PrizeDrawEntryActions.d.ts +15 -1
  249. package/dist/features/products/components/PrizeDrawEntryActions.js +70 -8
  250. package/dist/features/products/components/ProductDetailPageView.js +74 -15
  251. package/dist/features/products/components/ProductForm.d.ts +13 -1
  252. package/dist/features/products/components/ProductForm.js +16 -2
  253. package/dist/features/products/components/ProductsIndexListing.d.ts +16 -1
  254. package/dist/features/products/components/ProductsIndexListing.js +3 -3
  255. package/dist/features/products/components/ShowGroupSection.js +15 -2
  256. package/dist/features/products/components/SparesListView.d.ts +7 -0
  257. package/dist/features/products/components/SparesListView.js +39 -0
  258. package/dist/features/products/constants/action-defs.d.ts +1 -0
  259. package/dist/features/products/constants/action-defs.js +1 -0
  260. package/dist/features/products/repository/products.repository.d.ts +98 -0
  261. package/dist/features/products/repository/products.repository.js +235 -17
  262. package/dist/features/products/schemas/firestore.d.ts +97 -4
  263. package/dist/features/products/schemas/firestore.js +104 -0
  264. package/dist/features/products/schemas/index.d.ts +10 -19
  265. package/dist/features/products/schemas/index.js +23 -6
  266. package/dist/features/products/types/index.d.ts +45 -1
  267. package/dist/features/products/utils/group-member-image.d.ts +39 -0
  268. package/dist/features/products/utils/group-member-image.js +3 -0
  269. package/dist/features/products/utils/listing-badge-variant.js +4 -0
  270. package/dist/features/reviews/components/ReviewsList.js +1 -1
  271. package/dist/features/scams/components/ScamProfileView.js +1 -1
  272. package/dist/features/search/components/EntityTypeahead.d.ts +44 -0
  273. package/dist/features/search/components/EntityTypeahead.js +92 -0
  274. package/dist/features/search/components/Search.d.ts +12 -1
  275. package/dist/features/search/components/Search.js +47 -3
  276. package/dist/features/search/components/SearchFacetRail.d.ts +11 -0
  277. package/dist/features/search/components/SearchFacetRail.js +92 -0
  278. package/dist/features/search/components/SearchResultsClient.d.ts +33 -0
  279. package/dist/features/search/components/SearchResultsClient.js +103 -0
  280. package/dist/features/search/components/SearchResultsPageView.d.ts +15 -1
  281. package/dist/features/search/components/SearchResultsPageView.js +2 -2
  282. package/dist/features/search/components/index.d.ts +0 -6
  283. package/dist/features/search/components/index.js +0 -3
  284. package/dist/features/search/hooks/useNavSuggestions.d.ts +13 -0
  285. package/dist/features/search/hooks/useScopedSearch.d.ts +34 -0
  286. package/dist/features/search/hooks/useScopedSearch.js +114 -0
  287. package/dist/features/search/hooks/useSiteSearch.d.ts +26 -0
  288. package/dist/features/search/hooks/useSiteSearch.js +149 -0
  289. package/dist/features/search/index.d.ts +0 -4
  290. package/dist/features/search/index.js +0 -4
  291. package/dist/features/search/manifest.d.ts +12 -0
  292. package/dist/features/search/manifest.js +17 -2
  293. package/dist/features/search/server.d.ts +0 -3
  294. package/dist/features/search/server.js +0 -3
  295. package/dist/features/seller/components/SellerListingTypeView.d.ts +1 -1
  296. package/dist/features/seller/components/SellerListingTypeView.js +20 -0
  297. package/dist/features/seller/components/SellerPayoutSettingsView.js +35 -14
  298. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  299. package/dist/features/seller/components/SellerProductShell.js +2 -1
  300. package/dist/features/seller/components/SellerSidebar.js +1 -1
  301. package/dist/features/seller/components/SellerSparesView.d.ts +17 -0
  302. package/dist/features/seller/components/SellerSparesView.js +6 -0
  303. package/dist/features/seller/components/index.d.ts +2 -0
  304. package/dist/features/seller/components/index.js +1 -0
  305. package/dist/features/shell/CommandPalette.js +1 -1
  306. package/dist/features/sticker-trace/schemas/firestore.d.ts +19 -0
  307. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  308. package/dist/features/stores/components/StoreDetailLayoutView.js +7 -82
  309. package/dist/features/stores/components/StoreHeader.js +1 -2
  310. package/dist/features/stores/components/StoreSparesPageView.d.ts +27 -0
  311. package/dist/features/stores/components/StoreSparesPageView.js +48 -0
  312. package/dist/features/stores/schemas/firestore.d.ts +19 -0
  313. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.d.ts +2 -0
  314. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.js +96 -0
  315. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  316. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +280 -45
  317. package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.js +54 -32
  318. package/dist/features/tester/seed-data/authored/content-discovery__parts-database.js +3 -2
  319. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.d.ts +2 -0
  320. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.js +73 -0
  321. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.d.ts +2 -0
  322. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.js +340 -0
  323. package/dist/features/tester/seed-data/authored/index.js +16 -0
  324. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.d.ts +1 -0
  325. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +57 -0
  326. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.d.ts +2 -0
  327. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.js +77 -0
  328. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.d.ts +2 -0
  329. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.js +58 -0
  330. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +5 -4
  331. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +372 -18
  332. package/dist/index.d.ts +17 -57
  333. package/dist/index.js +35 -96
  334. package/dist/next/routing/route-map.d.ts +42 -1
  335. package/dist/next/routing/route-map.js +45 -0
  336. package/dist/providers/db-firebase/base.repository.d.ts +22 -0
  337. package/dist/providers/db-firebase/base.repository.js +36 -0
  338. package/dist/schemas/registry.d.ts +15 -6
  339. package/dist/security/blind-index-tokens.d.ts +54 -0
  340. package/dist/security/blind-index-tokens.js +152 -0
  341. package/dist/security/index.d.ts +1 -1
  342. package/dist/security/index.js +1 -1
  343. package/dist/security/settings-encryption.d.ts +35 -0
  344. package/dist/security/settings-encryption.js +91 -0
  345. package/dist/seed/_helpers/brand-rows.js +38 -14
  346. package/dist/seed/_helpers/category-forest.js +73 -7
  347. package/dist/seed/_helpers/category-images-generated.d.ts +25 -6
  348. package/dist/seed/_helpers/category-images-generated.js +81 -6
  349. package/dist/seed/_helpers/category-models.d.ts +1 -1
  350. package/dist/seed/_helpers/category-models.js +7 -1
  351. package/dist/seed/_helpers/category-parts-glossary-map.js +8 -0
  352. package/dist/seed/_helpers/category-parts.d.ts +1 -1
  353. package/dist/seed/_helpers/category-parts.js +50 -2
  354. package/dist/seed/_helpers/character-features.d.ts +1 -1
  355. package/dist/seed/_helpers/character-features.js +2 -1
  356. package/dist/seed/_helpers/franchise-rows.js +10 -2
  357. package/dist/seed/_helpers/media.d.ts +47 -0
  358. package/dist/seed/_helpers/media.js +34 -0
  359. package/dist/seed/authenticity-knowledge-seed-data.d.ts +49 -5
  360. package/dist/seed/authenticity-knowledge-seed-data.js +10001 -549
  361. package/dist/seed/categories-seed-data.js +124 -20
  362. package/dist/seed/grouped-listings-seed-data.js +16 -0
  363. package/dist/seed/homepage-sections-seed-data.js +94 -5
  364. package/dist/seed/index.d.ts +2 -3
  365. package/dist/seed/index.js +2 -2
  366. package/dist/seed/manifest.js +3 -0
  367. package/dist/seed/media-assets-seed-data.d.ts +1 -1
  368. package/dist/seed/media-assets-seed-data.js +746 -196
  369. package/dist/seed/model-composition-seed-data.js +122 -6
  370. package/dist/seed/part-glossary-seed-data.d.ts +1 -1
  371. package/dist/seed/part-glossary-seed-data.js +37219 -463
  372. package/dist/seed/products-art-seed-data.js +7 -18
  373. package/dist/seed/products-auctions-seed-data.js +56 -47
  374. package/dist/seed/products-beyblade-x-seed-data.d.ts +2 -0
  375. package/dist/seed/products-beyblade-x-seed-data.js +441 -0
  376. package/dist/seed/products-catalogue-seed-data.d.ts +5 -5
  377. package/dist/seed/products-catalogue-seed-data.js +1500 -1240
  378. package/dist/seed/products-classifieds-seed-data.js +9 -27
  379. package/dist/seed/products-digital-codes-seed-data.js +9 -18
  380. package/dist/seed/products-live-items-seed-data.js +5 -13
  381. package/dist/seed/products-preorders-seed-data.js +67 -33
  382. package/dist/seed/products-prize-draws-seed-data.js +8 -17
  383. package/dist/seed/products-spares-seed-data.d.ts +2 -0
  384. package/dist/seed/products-spares-seed-data.js +368 -0
  385. package/dist/seed/products-standard-seed-data.js +39 -126
  386. package/dist/seed/products-stickers-seed-data.js +59 -15
  387. package/dist/seed/site-settings-seed-data.js +8 -0
  388. package/dist/seo/json-ld.d.ts +25 -0
  389. package/dist/seo/json-ld.js +28 -0
  390. package/dist/server-entry.d.ts +3 -1
  391. package/dist/server-entry.js +2 -2
  392. package/dist/server.d.ts +9 -9
  393. package/dist/server.js +27 -25
  394. package/dist/styles.css +202 -1
  395. package/dist/tailwind-input.css +31 -17
  396. package/dist/tailwind-utilities.css +1 -1
  397. package/dist/ui/components/Accordion.js +1 -1
  398. package/dist/ui/components/Breadcrumb.js +1 -1
  399. package/dist/ui/components/DetailPageGallery.js +0 -2
  400. package/dist/ui/components/DetailPageHero.js +0 -1
  401. package/dist/ui/components/DetailPageTabs.js +1 -1
  402. package/dist/ui/components/Divider.js +3 -3
  403. package/dist/ui/components/GatedPrice.js +5 -1
  404. package/dist/ui/components/HorizontalScroller.js +1 -1
  405. package/dist/ui/components/ListingLayout.js +3 -3
  406. package/dist/ui/components/MediaTabs.style.css +81 -0
  407. package/dist/ui/components/Pagination.js +1 -1
  408. package/dist/ui/components/PendingValue.d.ts +45 -0
  409. package/dist/ui/components/PendingValue.js +7 -0
  410. package/dist/ui/components/Radio.style.css +119 -0
  411. package/dist/ui/components/RatingDisplay.js +2 -2
  412. package/dist/ui/components/SettingsSection.js +0 -2
  413. package/dist/ui/components/SiteLogo.js +3 -0
  414. package/dist/ui/components/SiteMark.js +3 -0
  415. package/dist/ui/components/SortDropdown.js +1 -1
  416. package/dist/ui/components/SpecTable.d.ts +58 -0
  417. package/dist/ui/components/SpecTable.js +8 -0
  418. package/dist/ui/components/StarRating.js +1 -3
  419. package/dist/ui/components/SummaryCard.js +1 -1
  420. package/dist/ui/components/index.style.css +1 -0
  421. package/dist/ui/icons/icon-registry.d.ts +1 -0
  422. package/dist/ui/icons/icon-registry.js +9 -1
  423. package/dist/ui/index.d.ts +4 -0
  424. package/dist/ui/index.js +2 -0
  425. package/dist/utils/search-txt-query.d.ts +12 -0
  426. package/dist/utils/search-txt-query.js +12 -0
  427. package/package.json +1 -1
  428. package/scripts/dedupe-peer-deps.mjs +18 -0
  429. package/scripts/seed-cli.mjs +135 -26
  430. package/scripts/verify-css-build.mjs +118 -37
  431. package/dist/_internal/server/features/search/actions.d.ts +0 -7
  432. package/dist/_internal/server/features/search/actions.js +0 -21
  433. package/dist/_internal/server/features/search/data.d.ts +0 -15
  434. package/dist/_internal/server/features/search/data.js +0 -18
  435. package/dist/_internal/server/features/search/index.d.ts +0 -3
  436. package/dist/_internal/server/features/search/index.js +0 -2
  437. package/dist/features/homepage/api/[id]/route.d.ts +0 -23
  438. package/dist/features/homepage/api/[id]/route.js +0 -103
  439. package/dist/features/homepage/api/route.d.ts +0 -14
  440. package/dist/features/homepage/api/route.js +0 -140
  441. package/dist/features/homepage/api/sections/[id]/route.d.ts +0 -26
  442. package/dist/features/homepage/api/sections/[id]/route.js +0 -95
  443. package/dist/features/homepage/api/sections/route.d.ts +0 -13
  444. package/dist/features/homepage/api/sections/route.js +0 -82
  445. package/dist/features/homepage/components/AdvertisementBanner.d.ts +0 -14
  446. package/dist/features/homepage/components/AdvertisementBanner.js +0 -35
  447. package/dist/features/homepage/components/BeforeAfterCard.d.ts +0 -9
  448. package/dist/features/homepage/components/BeforeAfterCard.js +0 -73
  449. package/dist/features/homepage/components/FeaturedResultsSection.d.ts +0 -17
  450. package/dist/features/homepage/components/FeaturedResultsSection.js +0 -17
  451. package/dist/features/homepage/components/HeroBanner.d.ts +0 -7
  452. package/dist/features/homepage/components/HeroBanner.js +0 -43
  453. package/dist/features/homepage/components/HeroSection.d.ts +0 -7
  454. package/dist/features/homepage/components/HeroSection.js +0 -6
  455. package/dist/features/homepage/components/HomepageSkeleton.d.ts +0 -2
  456. package/dist/features/homepage/components/HomepageSkeleton.js +0 -21
  457. package/dist/features/homepage/components/HomepageView.d.ts +0 -25
  458. package/dist/features/homepage/components/HomepageView.js +0 -5
  459. package/dist/features/homepage/components/NewsletterBanner.d.ts +0 -23
  460. package/dist/features/homepage/components/NewsletterBanner.js +0 -37
  461. package/dist/features/homepage/components/SiteFeaturesSection.d.ts +0 -14
  462. package/dist/features/homepage/components/SiteFeaturesSection.js +0 -11
  463. package/dist/features/homepage/components/TrustBadges.d.ts +0 -6
  464. package/dist/features/homepage/components/TrustBadges.js +0 -46
  465. package/dist/features/homepage/components/TrustIndicatorsSection.d.ts +0 -12
  466. package/dist/features/homepage/components/TrustIndicatorsSection.js +0 -11
  467. package/dist/features/homepage/hooks/useHomepage.d.ts +0 -11
  468. package/dist/features/homepage/hooks/useHomepage.js +0 -17
  469. package/dist/features/homepage/hooks/useHomepageSections.d.ts +0 -2
  470. package/dist/features/homepage/hooks/useHomepageSections.js +0 -10
  471. package/dist/features/homepage/repository/homepage.repository.d.ts +0 -11
  472. package/dist/features/homepage/repository/homepage.repository.js +0 -25
  473. package/dist/features/search/actions/index.d.ts +0 -1
  474. package/dist/features/search/actions/index.js +0 -1
  475. package/dist/features/search/actions/search-actions.d.ts +0 -18
  476. package/dist/features/search/actions/search-actions.js +0 -43
  477. package/dist/features/search/api/route.d.ts +0 -22
  478. package/dist/features/search/api/route.js +0 -128
  479. package/dist/features/search/columns/index.d.ts +0 -17
  480. package/dist/features/search/columns/index.js +0 -49
  481. package/dist/features/search/components/SearchFiltersRow.d.ts +0 -22
  482. package/dist/features/search/components/SearchFiltersRow.js +0 -21
  483. package/dist/features/search/components/SearchResultsSection.d.ts +0 -53
  484. package/dist/features/search/components/SearchResultsSection.js +0 -35
  485. package/dist/features/search/components/SearchView.d.ts +0 -27
  486. package/dist/features/search/components/SearchView.js +0 -8
  487. package/dist/features/search/hooks/useSearch.d.ts +0 -21
  488. package/dist/features/search/hooks/useSearch.js +0 -33
  489. package/dist/features/search/repository/search.repository.d.ts +0 -14
  490. package/dist/features/search/repository/search.repository.js +0 -59
  491. package/dist/features/search/schemas/index.d.ts +0 -70
  492. package/dist/features/search/schemas/index.js +0 -36
  493. package/dist/features/search/types/index.d.ts +0 -48
  494. package/dist/features/stores/components/StoreScopedSearch.d.ts +0 -17
  495. package/dist/features/stores/components/StoreScopedSearch.js +0 -27
  496. package/dist/seed/defaults/homepage-sections.d.ts +0 -2
  497. package/dist/seed/defaults/homepage-sections.js +0 -60
  498. package/dist/seed/factories/homepage-section.factory.d.ts +0 -10
  499. package/dist/seed/factories/homepage-section.factory.js +0 -13
  500. /package/dist/{features/search/types/index.js → _internal/shared/listing-types/spares/og.d.ts} +0 -0
@@ -12,7 +12,7 @@ function toArray(value) {
12
12
  return Array.isArray(value) ? value : [value];
13
13
  }
14
14
  function renderLegacyAccordion({ title, children, open, className = "", titleClassName = "", contentClassName = "", }) {
15
- return (_jsxs("details", { open: open, className: `appkit-accordion appkit-accordion--legacy ${className}`, children: [_jsxs("summary", { className: `appkit-accordion__summary ${titleClassName}`, children: [title, _jsx("span", { className: "appkit-accordion__chevron", "aria-hidden": "true", children: "\u25BE" })] }), _jsx("div", { className: `appkit-accordion__content ${contentClassName}`, "data-section": "accordion-div-447", children: children })] }));
15
+ return (_jsxs("details", { open: open, className: `appkit-accordion ${className}`, children: [_jsxs("summary", { className: `appkit-accordion__summary ${titleClassName}`, children: [title, _jsx("span", { className: "appkit-accordion__chevron", "aria-hidden": "true", children: "\u25BE" })] }), _jsx("div", { className: `appkit-accordion__content ${contentClassName}`, "data-section": "accordion-div-447", children: children })] }));
16
16
  }
17
17
  export function Accordion({ title, children, open = false, className = "", titleClassName = "", contentClassName = "", type = "single", defaultValue, value, onChange, }) {
18
18
  // useMemo/useState must run unconditionally on every render — they were
@@ -4,7 +4,7 @@ import { Nav, Ol, Li } from "./Semantic.js";
4
4
  import { Span } from "./Typography.js";
5
5
  import { TextLink } from "./TextLink.js";
6
6
  export function Breadcrumb({ items, className = "", tone = "default" }) {
7
- return (_jsx(Nav, { "aria-label": "Breadcrumb", className: `appkit-breadcrumb ${tone === "on-media" ? "appkit-breadcrumb--on-media" : ""} ${className}`, children: _jsx(Ol, { className: "appkit-breadcrumb__list", children: items.map((item, i) => {
7
+ return (_jsx(Nav, { "aria-label": "Breadcrumb", className: `${tone === "on-media" ? "appkit-breadcrumb--on-media" : ""} ${className}`, children: _jsx(Ol, { className: "appkit-breadcrumb__list", children: items.map((item, i) => {
8
8
  const isLast = i === items.length - 1;
9
9
  return (_jsxs(Li, { className: "appkit-breadcrumb__item", children: [i > 0 && (_jsx(ChevronRight, { className: "appkit-breadcrumb__separator", "aria-hidden": "true" })), isLast || !item.href ? (_jsx(Span, { className: isLast
10
10
  ? "appkit-breadcrumb__current"
@@ -24,7 +24,6 @@ export function DetailPageGallery({ images, title, aspect = "square", fallback,
24
24
  const [activeIndex, setActiveIndex] = useState(Math.min(Math.max(initialIndex, 0), Math.max(images.length - 1, 0)));
25
25
  if (!images.length) {
26
26
  return (_jsx(Div, { className: [
27
- "appkit-detail-gallery",
28
27
  "w-full overflow-hidden rounded-2xl bg-[var(--appkit-color-surface)]",
29
28
  ASPECT_CLASS[aspect],
30
29
  className,
@@ -34,7 +33,6 @@ export function DetailPageGallery({ images, title, aspect = "square", fallback,
34
33
  }
35
34
  const active = images[activeIndex] ?? images[0];
36
35
  return (_jsxs(Div, { className: [
37
- "appkit-detail-gallery",
38
36
  "w-full space-y-2",
39
37
  className,
40
38
  ]
@@ -13,7 +13,6 @@ import { Heading, Text } from "./Typography.js";
13
13
  */
14
14
  export function DetailPageHero({ title, eyebrow, subtitle, metaRow, description, mediaSlot, actionsSlot, belowActions, className, }) {
15
15
  return (_jsxs(Row, { gap: "lg", align: "start", className: [
16
- "appkit-detail-hero",
17
16
  "flex-col md:flex-row",
18
17
  className,
19
18
  ]
@@ -11,7 +11,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "./Tabs.js";
11
11
  * W1-14 — extracted 2026-05-23.
12
12
  */
13
13
  export function DetailPageTabs({ tabs, activeTab, defaultTab, onTabChange, className, }) {
14
- return (_jsxs(Tabs, { value: activeTab, defaultValue: defaultTab ?? tabs[0]?.id ?? "", onChange: onTabChange, className: ["appkit-detail-tabs", "space-y-4", className].filter(Boolean).join(" "), children: [_jsx(TabsList, { children: tabs.map((tab) => {
14
+ return (_jsxs(Tabs, { value: activeTab, defaultValue: defaultTab ?? tabs[0]?.id ?? "", onChange: onTabChange, className: ["space-y-4", className].filter(Boolean).join(" "), children: [_jsx(TabsList, { children: tabs.map((tab) => {
15
15
  const label = typeof tab.label === "string" ? tab.label : undefined;
16
16
  return (_jsx(TabsTrigger, { value: tab.id, disabled: tab.disabled, badge: tab.count, label: label, children: tab.label }, tab.id));
17
17
  }) }), tabs.map((tab) => (_jsx(TabsContent, { value: tab.id, children: _jsx(Div, { children: tab.content }) }, tab.id)))] }));
@@ -2,10 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Span } from "./Typography.js";
3
3
  export function Divider({ label, orientation = "horizontal", className = "", }) {
4
4
  if (orientation === "vertical") {
5
- return (_jsx("div", { className: `appkit-divider appkit-divider--vertical ${className}`, role: "separator", "aria-orientation": "vertical" }));
5
+ return (_jsx("div", { className: `appkit-divider--vertical ${className}`, role: "separator", "aria-orientation": "vertical" }));
6
6
  }
7
7
  if (label) {
8
- return (_jsxs("div", { className: `appkit-divider appkit-divider--labeled ${className}`, role: "separator", "data-section": "divider-div-479", children: [_jsx("div", { className: "appkit-divider__line" }), _jsx(Span, { className: "appkit-divider__label", children: label }), _jsx("div", { className: "appkit-divider__line" })] }));
8
+ return (_jsxs("div", { className: `appkit-divider--labeled ${className}`, role: "separator", "data-section": "divider-div-479", children: [_jsx("div", { className: "appkit-divider__line" }), _jsx(Span, { className: "appkit-divider__label", children: label }), _jsx("div", { className: "appkit-divider__line" })] }));
9
9
  }
10
- return (_jsx("div", { className: `appkit-divider appkit-divider--horizontal ${className}`, role: "separator", "aria-orientation": "horizontal" }));
10
+ return (_jsx("div", { className: `appkit-divider--horizontal ${className}`, role: "separator", "aria-orientation": "horizontal" }));
11
11
  }
@@ -18,6 +18,10 @@ import { useCanSeePrices } from "../../react/hooks/useCanSeePrices.js";
18
18
  * It is rendered in EVERY state — signed in, signed out and resolving — because
19
19
  * the markup describes the region, not the refusal.
20
20
  */
21
+ // A SELECTOR TARGET, not a style — gatedPriceWebPageJsonLd names it in
22
+ // `hasPart.cssSelector` so a crawler can see the gate is declared. It must
23
+ // stay rule-less: styling it would change what the markup describes.
24
+ // audit-dead-css-ok: selector target for the paywall JSON-LD, never styled
21
25
  export const GATED_PRICE_CLASS = "appkit-gated-price";
22
26
  const DEFAULT_LABEL = "Sign in to see price";
23
27
  /**
@@ -76,5 +80,5 @@ export function GatedPrice({ amount, currency = getDefaultCurrency(), originalAm
76
80
  const originalClass = variant === "detail"
77
81
  ? "appkit-price-display__original appkit-price-display__original--detail"
78
82
  : "appkit-price-display__original appkit-price-display__original--compact";
79
- return (_jsxs(Row, { wrap: true, align: "baseline", gap: "xs", className: `appkit-price-display ${rootClass}`, children: [_jsx(Span, { className: priceClass, children: formatCurrency(amount, currency) }), hasDiscount && (_jsxs(_Fragment, { children: [_jsx(Span, { className: originalClass, children: formatCurrency(originalAmount, currency) }), _jsxs(Span, { className: "appkit-price-display__discount", children: ["-", formatPercentage(discountPct, 0)] })] }))] }));
83
+ return (_jsxs(Row, { wrap: true, align: "baseline", gap: "xs", className: rootClass, children: [_jsx(Span, { className: priceClass, children: formatCurrency(amount, currency) }), hasDiscount && (_jsxs(_Fragment, { children: [_jsx(Span, { className: originalClass, children: formatCurrency(originalAmount, currency) }), _jsxs(Span, { className: "appkit-price-display__discount", children: ["-", formatPercentage(discountPct, 0)] })] }))] }));
80
84
  }
@@ -153,7 +153,7 @@ export function HorizontalScroller({ children, className = "", gap = 16, snapToI
153
153
  // Grid mode: group items into slides of (rows × colCount) cards.
154
154
  Array.from({ length: gridSlideCount }, (_, slideIndex) => {
155
155
  const slideItems = normalizedItems.slice(slideIndex * gridCardsPerSlide, (slideIndex + 1) * gridCardsPerSlide);
156
- return (_jsx("div", { className: "appkit-hscroller__slide", style: {
156
+ return (_jsx("div", { style: {
157
157
  display: "grid",
158
158
  gridTemplateColumns: `repeat(${gridCols}, 1fr)`,
159
159
  gap: `${gap}px`,
@@ -95,10 +95,10 @@ export function ListingLayout({ headerSlot, statusTabsSlot, filterContent, filte
95
95
  effectiveIsDashboard
96
96
  ? "appkit-listing-layout__toolbar--dashboard"
97
97
  : "appkit-listing-layout__toolbar--page",
98
- ].join(" "), children: [_jsxs(Div, { className: "appkit-listing-layout__toolbar-row appkit-listing-layout__toolbar-row--desktop", children: [hasFilter && (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setSidebarOpen((prev) => !prev), "aria-label": sidebarOpen ? l.hideFilters : l.showFilters, "aria-expanded": sidebarOpen, className: [
98
+ ].join(" "), children: [_jsxs(Div, { className: "appkit-listing-layout__toolbar-row--desktop", children: [hasFilter && (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setSidebarOpen((prev) => !prev), "aria-label": sidebarOpen ? l.hideFilters : l.showFilters, "aria-expanded": sidebarOpen, className: [
99
99
  "appkit-listing-layout__filter-btn",
100
100
  sidebarOpen ? "appkit-listing-layout__filter-btn--active" : "",
101
- ].join(" "), children: [_jsx(FilterIcon, {}), l.filtersTitle, filterActiveCount > 0 && (_jsx(Span, { className: "appkit-listing-layout__filter-badge", "aria-label": l.filterActiveCount(filterActiveCount), children: filterActiveCount }))] })), searchSlot && (_jsx(Div, { className: "appkit-listing-layout__search", children: searchSlot })), _jsxs(Div, { className: "appkit-listing-layout__toolbar-actions", children: [sortSlot, viewToggleSlot && (_jsx(Div, { className: "appkit-listing-layout__view-toggle-wrap", children: viewToggleSlot })), actionsSlot] }), toolbarPaginationSlot && (_jsx(Div, { className: "appkit-listing-layout__toolbar-pagination", children: toolbarPaginationSlot }))] }), !mobileToolbarCollapsed && (_jsxs(Div, { className: "appkit-listing-layout__toolbar-row appkit-listing-layout__toolbar-row--mobile", children: [_jsxs(Div, { className: "appkit-listing-layout__mobile-row-1", children: [hasFilter && (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setMobileFilterOpen(true), "aria-label": l.filtersTitle, className: [
101
+ ].join(" "), children: [_jsx(FilterIcon, {}), l.filtersTitle, filterActiveCount > 0 && (_jsx(Span, { className: "appkit-listing-layout__filter-badge", "aria-label": l.filterActiveCount(filterActiveCount), children: filterActiveCount }))] })), searchSlot && (_jsx(Div, { className: "appkit-listing-layout__search", children: searchSlot })), _jsxs(Div, { className: "appkit-listing-layout__toolbar-actions", children: [sortSlot, viewToggleSlot && (_jsx(Div, { className: "appkit-listing-layout__view-toggle-wrap", children: viewToggleSlot })), actionsSlot] }), toolbarPaginationSlot && (_jsx(Div, { className: "appkit-listing-layout__toolbar-pagination", children: toolbarPaginationSlot }))] }), !mobileToolbarCollapsed && (_jsxs(Div, { className: "appkit-listing-layout__toolbar-row--mobile", children: [_jsxs(Div, { className: "appkit-listing-layout__mobile-row-1", children: [hasFilter && (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setMobileFilterOpen(true), "aria-label": l.filtersTitle, className: [
102
102
  "appkit-listing-layout__filter-btn",
103
103
  filterActiveCount > 0
104
104
  ? "appkit-listing-layout__filter-btn--active"
@@ -117,7 +117,7 @@ export function ListingLayout({ headerSlot, statusTabsSlot, filterContent, filte
117
117
  : "appkit-listing-layout__sidebar--collapsed",
118
118
  ].join(" "), children: _jsxs(Div, { className: "appkit-listing-layout__sidebar-panel", children: [_jsxs(Div, { className: "appkit-listing-layout__sidebar-header", children: [_jsx(Text, { weight: "semibold", size: "sm", children: panelTitle }), filterActiveCount > 0 && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: onFilterClear, className: "text-xs text-primary hover:text-primary/80 hover:underline p-0 h-auto leading-none font-medium", children: l.clearAll }))] }), _jsx(Div, { className: "appkit-listing-layout__sidebar-facets", children: filterContent }), _jsx(Div, { className: "appkit-listing-layout__sidebar-footer", children: _jsx(Button, { type: "button", variant: "primary", className: "w-full rounded-xl", size: "sm", onClick: onFilterApply, children: filterPendingCount != null && filterPendingCount > 0
119
119
  ? `${l.applyFilters} (${filterPendingCount})`
120
- : l.applyFilters }) })] }) })), _jsxs(Div, { className: "appkit-listing-layout__content", children: [activeFiltersSlot, resultCountSlot && (_jsx(Div, { className: "appkit-listing-layout__result-count", children: resultCountSlot })), errorSlot ? (errorSlot) : (_jsxs(_Fragment, { children: [children, paginationSlot && (_jsx(Div, { className: "appkit-listing-layout__pagination", children: paginationSlot }))] }))] })] }), toolbarPaginationSlot &&
120
+ : l.applyFilters }) })] }) })), _jsxs(Div, { className: "appkit-listing-layout__content", children: [activeFiltersSlot, resultCountSlot && (_jsx(Div, { children: resultCountSlot })), errorSlot ? (errorSlot) : (_jsxs(_Fragment, { children: [children, paginationSlot && (_jsx(Div, { className: "appkit-listing-layout__pagination", children: paginationSlot }))] }))] })] }), toolbarPaginationSlot &&
121
121
  bottomChromeSlot &&
122
122
  createPortal(_jsx(Nav, { "aria-label": "Pagination", className: "appkit-listing-layout__mobile-pagination", children: toolbarPaginationSlot }), bottomChromeSlot), hasFilter && (_jsx(Drawer, { isOpen: mobileFilterOpen, onClose: () => setMobileFilterOpen(false), side: "bottom", title: filterActiveCount > 0
123
123
  ? `${panelTitle} (${filterActiveCount})`
@@ -0,0 +1,81 @@
1
+ /*
2
+ * Media source/segment tab strips — MediaPickerModal and MediaUploadField.
3
+ *
4
+ * 🛑 Both strips shipped with NO rules at all. `MediaPickerModal` ("Upload file"
5
+ * / "Choose existing") and `MediaUploadField` ("Upload" / "YouTube" /
6
+ * "External URL") each render raw `<button>`s carrying `appkit-media-*` class
7
+ * names, and no stylesheet ever defined them — so the one control that tells a
8
+ * seller which media SOURCE they are using rendered as bare browser buttons,
9
+ * with no indication of which was active. Found 2026-10-19 by
10
+ * `audit-dead-css-classes` once the blanket `appkit-` exemption came off.
11
+ *
12
+ * The two families are kept DISTINCT rather than collapsed into one
13
+ * `appkit-tab-strip`: renaming would mean editing both components plus any
14
+ * consumer override keyed on the old names, for no behavioural gain. They
15
+ * share declarations through the selector lists below instead, so the two
16
+ * strips cannot drift apart visually.
17
+ *
18
+ * Colours come from tokens, never a palette literal — a hardcoded `zinc-100`
19
+ * fill is the same near-white in every theme (Recurrent Root Cause #79).
20
+ */
21
+
22
+ .appkit-media-picker__tabs,
23
+ .appkit-media-upload__source-tabs {
24
+ display: inline-flex;
25
+ align-items: stretch;
26
+ gap: 0;
27
+ border: 1px solid var(--appkit-color-border);
28
+ border-radius: var(--appkit-radius-lg);
29
+ background: var(--appkit-color-surface-input);
30
+ padding: 2px;
31
+ overflow: hidden;
32
+ max-width: 100%;
33
+ }
34
+
35
+ .appkit-media-picker__tab-btn,
36
+ .appkit-media-upload__source-tab {
37
+ appearance: none;
38
+ border: 0;
39
+ background: transparent;
40
+ cursor: pointer;
41
+ white-space: nowrap;
42
+ padding: var(--appkit-space-1-5) var(--appkit-space-3);
43
+ border-radius: var(--appkit-radius-md);
44
+ font-size: var(--appkit-text-sm);
45
+ font-weight: 500;
46
+ line-height: 1.25rem;
47
+ color: var(--appkit-color-text-muted);
48
+ transition: background-color 0.15s ease, color 0.15s ease;
49
+ }
50
+
51
+ .appkit-media-picker__tab-btn:hover:not(:disabled),
52
+ .appkit-media-upload__source-tab:hover:not(:disabled) {
53
+ background: var(--appkit-color-surface-hover);
54
+ color: var(--appkit-color-text);
55
+ }
56
+
57
+ .appkit-media-picker__tab-btn:focus-visible,
58
+ .appkit-media-upload__source-tab:focus-visible {
59
+ outline: 2px solid var(--appkit-color-focus-ring);
60
+ outline-offset: -2px;
61
+ }
62
+
63
+ /*
64
+ * The active tab is the only one that gets a raised surface. `--active` must
65
+ * win over `:hover` for the selected tab, so it is declared after the hover
66
+ * rule rather than relying on specificity.
67
+ */
68
+ .appkit-media-picker__tab-btn--active,
69
+ .appkit-media-upload__source-tab--active,
70
+ .appkit-media-picker__tab-btn--active:hover,
71
+ .appkit-media-upload__source-tab--active:hover {
72
+ background: var(--appkit-color-surface);
73
+ color: var(--appkit-color-text);
74
+ box-shadow: var(--appkit-shadow-sm);
75
+ }
76
+
77
+ .appkit-media-picker__tab-btn:disabled,
78
+ .appkit-media-upload__source-tab:disabled {
79
+ cursor: not-allowed;
80
+ opacity: 0.6;
81
+ }
@@ -58,5 +58,5 @@ export function Pagination({ currentPage, totalPages, onPageChange, paginationCo
58
58
  return `${base} appkit-pagination__button--default`;
59
59
  };
60
60
  const pages = getPageNumbers(currentPage, totalPages, maxVisible);
61
- return (_jsxs("nav", { className: `appkit-pagination ${className}`, "aria-label": "Pagination", children: [showFirstLast && (_jsx("button", { type: "button", className: btnClass(false, disabled || currentPage === 1), onClick: () => handle(1), disabled: disabled || currentPage === 1, "aria-label": "First page", children: "\u00AB" })), showPrevNext && (_jsx("button", { type: "button", className: btnClass(false, disabled || currentPage === 1), onClick: () => handle(currentPage - 1), disabled: disabled || currentPage === 1, "aria-label": "Previous page", children: "\u2039" })), pages.map((page, i) => page === "..." ? (_jsx("span", { className: `appkit-pagination__ellipsis ${SIZE_CLASSES[size]}`, "aria-hidden": "true", children: "\u2026" }, `ellipsis-${i}`)) : (_jsx("button", { type: "button", className: btnClass(page === currentPage, disabled && page !== currentPage), onClick: () => handle(page), disabled: disabled, "aria-label": `Page ${page}`, "aria-current": page === currentPage ? "page" : undefined, children: page }, page))), showPrevNext && (_jsx("button", { type: "button", className: btnClass(false, disabled || currentPage === totalPages), onClick: () => handle(currentPage + 1), disabled: disabled || currentPage === totalPages, "aria-label": "Next page", children: "\u203A" })), showFirstLast && (_jsx("button", { type: "button", className: btnClass(false, disabled || currentPage === totalPages), onClick: () => handle(totalPages), disabled: disabled || currentPage === totalPages, "aria-label": "Last page", children: "\u00BB" })), showPageSizeSelector && (_jsx(Select, { "aria-label": "Rows per page", value: String(pageSize), onValueChange: (next) => onPageSizeChange(Number(next)), options: resolved.pageSizeOptions.map((n) => ({ label: `${n} / page`, value: String(n) })), disabled: disabled, className: "appkit-pagination__page-size" }))] }));
61
+ return (_jsxs("nav", { className: `appkit-pagination ${className}`, "aria-label": "Pagination", children: [showFirstLast && (_jsx("button", { type: "button", className: btnClass(false, disabled || currentPage === 1), onClick: () => handle(1), disabled: disabled || currentPage === 1, "aria-label": "First page", children: "\u00AB" })), showPrevNext && (_jsx("button", { type: "button", className: btnClass(false, disabled || currentPage === 1), onClick: () => handle(currentPage - 1), disabled: disabled || currentPage === 1, "aria-label": "Previous page", children: "\u2039" })), pages.map((page, i) => page === "..." ? (_jsx("span", { className: `appkit-pagination__ellipsis ${SIZE_CLASSES[size]}`, "aria-hidden": "true", children: "\u2026" }, `ellipsis-${i}`)) : (_jsx("button", { type: "button", className: btnClass(page === currentPage, disabled && page !== currentPage), onClick: () => handle(page), disabled: disabled, "aria-label": `Page ${page}`, "aria-current": page === currentPage ? "page" : undefined, children: page }, page))), showPrevNext && (_jsx("button", { type: "button", className: btnClass(false, disabled || currentPage === totalPages), onClick: () => handle(currentPage + 1), disabled: disabled || currentPage === totalPages, "aria-label": "Next page", children: "\u203A" })), showFirstLast && (_jsx("button", { type: "button", className: btnClass(false, disabled || currentPage === totalPages), onClick: () => handle(totalPages), disabled: disabled || currentPage === totalPages, "aria-label": "Last page", children: "\u00BB" })), showPageSizeSelector && (_jsx(Select, { "aria-label": "Rows per page", value: String(pageSize), onValueChange: (next) => onPageSizeChange(Number(next)), options: resolved.pageSizeOptions.map((n) => ({ label: `${n} / page`, value: String(n) })), disabled: disabled }))] }));
62
62
  }
@@ -0,0 +1,45 @@
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * PendingValue — renders a value, or a VISIBLY incomplete marker when it is
4
+ * not yet decided.
5
+ *
6
+ * ## Why a marker and not a blank
7
+ *
8
+ * This exists for the statutory disclosure fields in `appkit.config.js` →
9
+ * `business`: support email, grievance officer, cancellation window, refund
10
+ * timeline. Each is `null` until someone decides it, and each appears on a
11
+ * page whose entire purpose is to publish it.
12
+ *
13
+ * Rendering `null` as an empty string makes an undisclosed legal obligation
14
+ * look like a design choice — the row is there, the label is there, and the
15
+ * value is simply missing in a way nobody notices. This renders
16
+ * `[to be confirmed]` in a warning chip instead, so the gap is obvious to
17
+ * whoever opens the page.
18
+ *
19
+ * 🛑 The alternative that must NOT be taken is inventing a plausible default.
20
+ * A made-up support phone number or a guessed return window on a published
21
+ * policy page is worse than an obviously missing one: it is wrong, it looks
22
+ * authoritative, and a customer may rely on it.
23
+ *
24
+ * ## Pairing
25
+ *
26
+ * `bg-warning-surface` with `text-warning` — the inline-chip pairing from
27
+ * CLAUDE.md Root Cause #67. Both tokens invert together with the theme, so
28
+ * this stays readable in light and dark. Never `text-white` against a
29
+ * `-surface` background; that is invisible in exactly one theme.
30
+ */
31
+ export interface PendingValueProps {
32
+ /** The resolved value. `null` / `undefined` / `""` all render the marker. */
33
+ value?: string | null;
34
+ /**
35
+ * What is missing, e.g. "Support email".
36
+ *
37
+ * Used for the accessible label so a screen reader hears
38
+ * "Support email: to be confirmed" rather than a bare "to be confirmed"
39
+ * detached from the row it belongs to.
40
+ */
41
+ label: string;
42
+ /** Rendered instead of the raw value when present — e.g. a `mailto:` link. */
43
+ children?: ReactNode;
44
+ }
45
+ export declare function PendingValue({ value, label, children }: PendingValueProps): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ export function PendingValue({ value, label, children }) {
3
+ if (value) {
4
+ return _jsx(_Fragment, { children: children ?? value });
5
+ }
6
+ return (_jsx("span", { className: "inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs font-medium bg-warning-surface text-warning", "aria-label": `${label}: to be confirmed`, children: "[to be confirmed]" }));
7
+ }
@@ -151,3 +151,122 @@
151
151
  .dark .appkit-radio-toggle__dot-inner {
152
152
  background: var(--appkit-color-bg);
153
153
  }
154
+
155
+ /* ──────────────────────────────────────────────────────────────────────────
156
+ RadioItem — the standalone single radio, a structural MIRROR of Checkbox.
157
+ `RadioItem` was written by copying `Checkbox.tsx` element-for-element
158
+ (`__label`, `__label--disabled`, `__box-wrap`, `__input`, `__input--error`,
159
+ `__content`, `__text`, `__error`) and the stylesheet half was never written,
160
+ so every one of those classes resolved to NO rule — a bare browser-default
161
+ radio with no spacing, no disabled dimming and no error state. It shipped
162
+ that way to the live poll on `/events/[id]`, its only call site.
163
+ Found 2026-10-19 by `audit-dead-css-classes` once the blanket `appkit-`
164
+ exemption was removed from NON_TAILWIND_PREFIXES.
165
+
166
+ Kept deliberately 1:1 with Checkbox.style.css rather than folded into the
167
+ `radio-classic` family above: that family is driven by RadioGroup's own
168
+ `UI_RADIO` class map with a JS-rendered dot, while this one styles a NATIVE
169
+ `<input type="radio">`. Two different mechanisms, two rule sets.
170
+ ────────────────────────────────────────────────────────────────────────── */
171
+
172
+ .appkit-radio-item {
173
+ width: 100%;
174
+ }
175
+
176
+ .appkit-radio-item__label {
177
+ display: inline-flex;
178
+ width: 100%;
179
+ cursor: pointer;
180
+ align-items: flex-start;
181
+ gap: 0.75rem;
182
+ }
183
+ .appkit-radio-item__label--disabled {
184
+ cursor: not-allowed;
185
+ opacity: 0.6;
186
+ }
187
+
188
+ .appkit-radio-item__box-wrap {
189
+ position: relative;
190
+ display: inline-flex;
191
+ margin-top: 2px;
192
+ height: 1.25rem;
193
+ width: 1.25rem;
194
+ flex-shrink: 0;
195
+ align-items: center;
196
+ justify-content: center;
197
+ }
198
+
199
+ /*
200
+ * `appearance: none` plus an inset box-shadow for the dot — the same technique
201
+ * Checkbox uses for its tick, and the reason the control can be themed at all.
202
+ * A native radio ignores `background-color` on most platforms.
203
+ */
204
+ .appkit-radio-item__input {
205
+ height: 1.25rem;
206
+ width: 1.25rem;
207
+ appearance: none;
208
+ border-radius: 9999px;
209
+ border: 1px solid var(--appkit-color-zinc-300);
210
+ background: var(--appkit-color-surface);
211
+ transition: all 0.15s ease;
212
+ cursor: pointer;
213
+ }
214
+ .appkit-radio-item__input:focus-visible {
215
+ outline: none;
216
+ box-shadow: 0 0 0 2px rgba(101, 196, 8, 0.3), 0 0 0 4px var(--appkit-color-surface);
217
+ }
218
+ .appkit-radio-item__input:not(:disabled):hover {
219
+ border-color: var(--appkit-color-secondary);
220
+ }
221
+ .appkit-radio-item__input:checked {
222
+ border-color: var(--appkit-color-secondary);
223
+ box-shadow: inset 0 0 0 4px var(--appkit-color-surface),
224
+ inset 0 0 0 1rem var(--appkit-color-secondary);
225
+ }
226
+ .appkit-radio-item__input:disabled {
227
+ cursor: not-allowed;
228
+ }
229
+ .appkit-radio-item__input--error {
230
+ border-color: var(--appkit-color-error);
231
+ }
232
+
233
+ .appkit-radio-item__content {
234
+ display: flex;
235
+ min-width: 0;
236
+ flex: 1;
237
+ align-items: flex-start;
238
+ justify-content: space-between;
239
+ gap: 0.75rem;
240
+ }
241
+
242
+ .appkit-radio-item__text {
243
+ padding-top: 2px;
244
+ font-size: 0.875rem;
245
+ /* `--appkit-color-text-muted` inverts per theme — no `.dark` override is
246
+ needed, unlike the raw zinc-700/zinc-200 pair this was copied from. */
247
+ color: var(--appkit-color-text-muted);
248
+ }
249
+
250
+ .appkit-radio-item__error {
251
+ margin-top: 0.375rem;
252
+ padding-left: 2rem;
253
+ }
254
+
255
+ .dark .appkit-radio-item__input {
256
+ border-color: var(--appkit-color-slate-600);
257
+ background: var(--appkit-color-surface);
258
+ }
259
+ .dark .appkit-radio-item__input:focus-visible {
260
+ box-shadow: 0 0 0 2px rgba(236, 72, 153, 0.3), 0 0 0 4px var(--appkit-color-bg);
261
+ }
262
+ .dark .appkit-radio-item__input:not(:disabled):hover {
263
+ border-color: var(--appkit-color-primary);
264
+ }
265
+ .dark .appkit-radio-item__input:checked {
266
+ border-color: var(--appkit-color-primary);
267
+ box-shadow: inset 0 0 0 4px var(--appkit-color-surface),
268
+ inset 0 0 0 1rem var(--appkit-color-primary);
269
+ }
270
+ .dark .appkit-radio-item__input--error {
271
+ border-color: var(--appkit-color-error);
272
+ }
@@ -9,6 +9,6 @@ const sizeClass = {
9
9
  export function RatingDisplay({ rating, maxRating = 5, size = "sm", showValue = false, className, }) {
10
10
  const starSize = sizeClass[size];
11
11
  return (_jsxs("div", { className: classNames("appkit-rating-display", className), "data-section": "ratingdisplay-div-576", children: [_jsx("div", { className: "appkit-rating-display__stars", "data-section": "ratingdisplay-div-577", children: Array.from({ length: maxRating }, (_, i) => i + 1).map((star) => (_jsx("svg", { className: classNames(starSize, star <= rating
12
- ? "appkit-rating-display__star appkit-rating-display__star--active"
13
- : "appkit-rating-display__star appkit-rating-display__star--inactive"), fill: "currentColor", viewBox: "0 0 20 20", "aria-hidden": "true", children: _jsx("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" }) }, star))) }), showValue && (_jsx(Span, { className: "appkit-rating-display__value", children: rating.toFixed(1) }))] }));
12
+ ? "appkit-rating-display__star--active"
13
+ : "appkit-rating-display__star--inactive"), fill: "currentColor", viewBox: "0 0 20 20", "aria-hidden": "true", children: _jsx("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" }) }, star))) }), showValue && (_jsx(Span, { className: "appkit-rating-display__value", children: rating.toFixed(1) }))] }));
14
14
  }
@@ -12,7 +12,6 @@ import { Toggle } from "./Toggle.js";
12
12
  */
13
13
  export function SettingsSection({ title, description, action, children, className, }) {
14
14
  return (_jsxs("section", { className: [
15
- "appkit-settings-section",
16
15
  "space-y-3 rounded-lg border border-[var(--appkit-color-border)] p-4",
17
16
  className,
18
17
  ]
@@ -29,7 +28,6 @@ export function SettingsSection({ title, description, action, children, classNam
29
28
  */
30
29
  export function ToggleRow({ label, description, checked, onChange, disabled = false, size = "md", className, }) {
31
30
  return (_jsxs("div", { className: [
32
- "appkit-toggle-row",
33
31
  "flex items-start justify-between gap-3 py-1",
34
32
  className,
35
33
  ]
@@ -14,6 +14,9 @@ import { useId } from "react";
14
14
  import { MediaImage } from "../../features/media/MediaImage.js";
15
15
  // Gradient ID prefix — made unique per instance via useId() to prevent
16
16
  // cross-SVG id conflicts when multiple SiteLogo components share the page.
17
+ // An SVG <linearGradient> ID prefix, not a class — suffixed with useId()
18
+ // and referenced as fill="url(#…)".
19
+ // audit-dead-css-ok: SVG gradient id, not a class
17
20
  const GRADIENT_ID_PREFIX = "appkit-logo-gradient";
18
21
  const SIZE_HEIGHTS = {
19
22
  sm: "h-5",
@@ -11,6 +11,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
11
  */
12
12
  import { useId } from "react";
13
13
  import { MediaImage } from "../../features/media/MediaImage.js";
14
+ // An SVG <linearGradient> ID prefix, not a class — suffixed with useId()
15
+ // and referenced as fill="url(#…)".
16
+ // audit-dead-css-ok: SVG gradient id, not a class
14
17
  const GRADIENT_ID_PREFIX = "appkit-mark-gradient";
15
18
  const SIZE_HEIGHTS = {
16
19
  sm: "h-5",
@@ -3,5 +3,5 @@ import { Row } from "./Layout.js";
3
3
  import { Select } from "./Select.js";
4
4
  import { Span } from "./Typography.js";
5
5
  export function SortDropdown({ value, onChange, options, label, className = "", countText, }) {
6
- return (_jsxs(Row, { gap: "sm", className: ["appkit-sort-dropdown", className].filter(Boolean).join(" "), children: [countText && (_jsx(Span, { variant: "secondary", size: "sm", className: "appkit-sort-dropdown__count", children: countText })), label && (_jsx(Span, { variant: "secondary", size: "sm", className: "appkit-sort-dropdown__label", children: label })), _jsx(Select, { value: value ?? "", onValueChange: onChange, options: options, className: "appkit-sort-dropdown__select", "aria-label": label ?? "Sort by" })] }));
6
+ return (_jsxs(Row, { gap: "sm", className: ["appkit-sort-dropdown", className].filter(Boolean).join(" "), children: [countText && (_jsx(Span, { variant: "secondary", size: "sm", children: countText })), label && (_jsx(Span, { variant: "secondary", size: "sm", className: "appkit-sort-dropdown__label", children: label })), _jsx(Select, { value: value ?? "", onValueChange: onChange, options: options, className: "appkit-sort-dropdown__select", "aria-label": label ?? "Sort by" })] }));
7
7
  }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * A labelled key/value specification table.
3
+ *
4
+ * ── 🛑 WHY THIS EXISTS: EIGHT BYTE-IDENTICAL COPIES ────────────────────────
5
+ *
6
+ * This exact `Dl` / `Row` / `Dt` / `Dd` composition was pasted at eight call
7
+ * sites — `ProductDetailPageView`, `AuctionDetailPageView`,
8
+ * `ClassifiedDetailPageView`, `DigitalCodeDetailPageView`,
9
+ * `LiveItemDetailPageView`, `PreOrderDetailPageView`, `BrandDetailPageView`
10
+ * and `CustomSectionTabContent` — with the same variants and the same
11
+ * `w-36 flex-shrink-0` label column in every one. The Duplication Decision
12
+ * Framework's Rule of Three was overshot nearly 3×, every copy accepts the
13
+ * same `{name, value, unit?}` row shape, and a styling fix had to be made
14
+ * eight times.
15
+ *
16
+ * ── 🛑 IT RENDERS NOTHING FOR AN EMPTY LIST, DELIBERATELY ──────────────────
17
+ *
18
+ * `bit-chip` and `face-bolt` parts have no specifications in any source we
19
+ * hold — 0 of 66 and 0 of 42, measured, and that is a fact about the sources
20
+ * rather than missing data. A table of em-dashes would claim we looked each
21
+ * value up and found none. The caller still decides whether to render a
22
+ * heading; this only guarantees the table itself is absent rather than empty.
23
+ *
24
+ * ── 🛑 `w-36` IS KEPT, NOT CONVERTED TO A VARIANT ──────────────────────────
25
+ *
26
+ * It is a fixed label-column width shared by all eight original call sites, so
27
+ * it belongs INSIDE the primitive — which is exactly where `audit-variant-ok`
28
+ * permits a raw utility. Converting it to a prop would re-open the question at
29
+ * every call site for no behaviour.
30
+ *
31
+ * @tag domain:ui
32
+ * @tag layer:primitive
33
+ * @tag pattern:none
34
+ * @tag access:server
35
+ */
36
+ import React from "react";
37
+ export interface SpecTableRow {
38
+ /** The label. "Weight", "Material", "Released (JP)". */
39
+ name: string;
40
+ /** The value, already formatted. */
41
+ value: string;
42
+ /** Appended after a space when present. "g", "mm". */
43
+ unit?: string;
44
+ /**
45
+ * Marks the value as approximate, rendered as a leading `≈`.
46
+ *
47
+ * 🛑 A per-row CONFIDENCE BADGE was the first design and is wrong: in a
48
+ * ten-row table it is noise that crowds out the values themselves. One
49
+ * glyph on the value plus a single footnote under the table says the same
50
+ * thing and stays readable — the caller owns the footnote.
51
+ */
52
+ approximate?: boolean;
53
+ }
54
+ export interface SpecTableProps {
55
+ rows: readonly SpecTableRow[];
56
+ className?: string;
57
+ }
58
+ export declare function SpecTable({ rows, className }: SpecTableProps): React.JSX.Element | null;
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Dl, Dt, Dd } from "./Semantic.js";
3
+ import { Row } from "./Layout.js";
4
+ export function SpecTable({ rows, className }) {
5
+ if (!rows.length)
6
+ return null;
7
+ return (_jsx(Dl, { divide: "subtle", rounded: "xl", border: "subtle", className: `overflow-hidden${className ? ` ${className}` : ""}`, children: rows.map((s, i) => (_jsxs(Row, { gap: "md", oddEven: "zebra", surface: "default", padding: "inline", children: [_jsx(Dt, { className: "w-36 flex-shrink-0", color: "primary", weight: "medium", children: s.name }), _jsxs(Dd, { className: "flex-1", color: "muted", children: [s.approximate ? "≈ " : "", s.value, s.unit ? ` ${s.unit}` : ""] })] }, `${s.name}-${i}`))) }));
8
+ }
@@ -9,9 +9,7 @@ export function StarRating({ value = 0, onChange, max = 5, size = "md", readOnly
9
9
  return (_jsxs(Span, { className: [
10
10
  "appkit-star-rating",
11
11
  `appkit-star-rating--${size}`,
12
- readOnly
13
- ? "appkit-star-rating--readonly"
14
- : "appkit-star-rating--interactive",
12
+ readOnly ? "" : "appkit-star-rating--interactive",
15
13
  className,
16
14
  ]
17
15
  .filter(Boolean)
@@ -10,5 +10,5 @@ const SUMMARY_CARD_VARIANT_CLASS = {
10
10
  export function SummaryCard({ lines, total, action, variant = "standalone", className, }) {
11
11
  return (_jsxs(Div, { className: classNames("appkit-summary-card", SUMMARY_CARD_VARIANT_CLASS[variant], className), children: [_jsx(Div, { className: "appkit-summary-card__lines", children: lines.map((line, i) => (_jsxs(Div, { className: "appkit-summary-card__line", children: [_jsx(Span, { className: "appkit-summary-card__label", children: line.label }), _jsx(Span, { className: line.muted
12
12
  ? "appkit-summary-card__value appkit-summary-card__value--muted"
13
- : "appkit-summary-card__value", children: line.value })] }, i))) }), _jsx(Divider, {}), _jsxs(Div, { className: "appkit-summary-card__total", children: [_jsx(Span, { className: "appkit-summary-card__total-label", children: total.label }), _jsx(Span, { className: "appkit-summary-card__total-value", children: total.value })] }), action && _jsx(Div, { className: "appkit-summary-card__action", children: action })] }));
13
+ : "appkit-summary-card__value", children: line.value })] }, i))) }), _jsx(Divider, {}), _jsxs(Div, { className: "appkit-summary-card__total", children: [_jsx(Span, { className: "appkit-summary-card__total-label", children: total.label }), _jsx(Span, { className: "appkit-summary-card__total-value", children: total.value })] }), action && _jsx(Div, { children: action })] }));
14
14
  }
@@ -75,6 +75,7 @@
75
75
  @import "./Div.style.css";
76
76
  @import "./Menu.style.css";
77
77
  @import "./OverflowRow.style.css";
78
+ @import "./MediaTabs.style.css";
78
79
  @import "./Semantic.style.css";
79
80
  @import "./UnsavedChangesModal.style.css";
80
81
  @import "../DataTable.style.css";
@@ -63,6 +63,7 @@ export declare const ICONS: {
63
63
  readonly digitalCode: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
64
64
  readonly art: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
65
65
  readonly stickers: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
66
+ readonly spares: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
66
67
  readonly live: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
67
68
  };
68
69
  /** Every valid `iconKey`. A typo is a compile error, not a silent blank. */
@@ -39,7 +39,7 @@
39
39
  * @tag consumers:Button,RowActionMenu,BulkActionBar,action-registry
40
40
  * @tag sideEffects:none
41
41
  */
42
- import { Archive, ArrowLeft, Ban, Bell, Check, CheckCircle, ChevronDown, Copy, Download, Edit, Eye, EyeOff, FileDown, Filter, Flag, Gavel, HelpCircle, Heart, Link as LinkIcon, Lock, Mail, Menu, MessageSquare, Moon, Package, Pause, Play, Plus, RefreshCw, Reply, RotateCcw, Save, Search, Send, Settings, Share2, ShieldCheck, ShoppingCart, Star, Sun, Scale, Tag, Trash2, TrendingUp, Truck, Upload, User, X, XCircle, CalendarClock, Gift, KeyRound, Palette, Sticker, PawPrint, } from "lucide-react";
42
+ import { Archive, ArrowLeft, Ban, Bell, Check, CheckCircle, ChevronDown, Copy, Download, Edit, Eye, EyeOff, FileDown, Filter, Flag, Gavel, HelpCircle, Heart, Link as LinkIcon, Lock, Mail, Menu, MessageSquare, Moon, Package, Pause, Play, Plus, RefreshCw, Reply, RotateCcw, Save, Search, Send, Settings, Share2, ShieldCheck, ShoppingCart, Star, Sun, Scale, Tag, Trash2, TrendingUp, Truck, Upload, User, X, XCircle, CalendarClock, Gift, KeyRound, Palette, Sticker, Puzzle, PawPrint, } from "lucide-react";
43
43
  /**
44
44
  * Semantic name → component.
45
45
  *
@@ -125,6 +125,14 @@ export const ICONS = {
125
125
  digitalCode: KeyRound,
126
126
  art: Palette,
127
127
  stickers: Sticker,
128
+ /*
129
+ * Nothing in the registry meant "a part", so this is minted rather than
130
+ * reused. `Puzzle` over `Cog`/`Wrench` because the semantic is "a piece that
131
+ * fits into something" — which is exactly what the spares feature is about,
132
+ * right down to the glossary's "Fits: …" cross-sell. A cog reads as
133
+ * machinery or settings, and `settings` already owns that glyph.
134
+ */
135
+ spares: Puzzle,
128
136
  live: PawPrint,
129
137
  };
130
138
  /**
@@ -16,6 +16,8 @@ export type { SectionProps, SectionBackgroundConfig, ArticleProps, MainProps, As
16
16
  export { Section, sectionBackgroundStyle, Article, Main, Aside, Nav, BlockHeader, BlockFooter, Ul, Ol, Li, Table, Thead, Tbody, Tr, Th, Td, Code, Pre, Blockquote, Figure, Figcaption, Dl, Dt, Dd, } from "./components/Semantic";
17
17
  export type { DivProps } from "./components/Div";
18
18
  export { Div } from "./components/Div";
19
+ export type { SpecTableProps, SpecTableRow } from "./components/SpecTable";
20
+ export { SpecTable } from "./components/SpecTable";
19
21
  export type { ColorVariant } from "./components/Typography";
20
22
  export { Heading, Text, Label, Caption, Span } from "./components/Typography";
21
23
  export { FilterChipGroup } from "./components/FilterChipGroup";
@@ -243,6 +245,8 @@ export { Scrim } from "./components/Scrim";
243
245
  export type { ScrimProps, ScrimDirection, ScrimIntensity } from "./components/Scrim";
244
246
  export { Kbd } from "./components/Kbd";
245
247
  export type { KbdProps, KbdSize, KbdTone } from "./components/Kbd";
248
+ export { PendingValue } from "./components/PendingValue";
249
+ export type { PendingValueProps } from "./components/PendingValue";
246
250
  export { StickyToolbar } from "./components/StickyToolbar";
247
251
  export type { StickyToolbarProps, StickyToolbarOffset, StickyToolbarTone, StickyToolbarPadding, } from "./components/StickyToolbar";
248
252
  export { Show, Hide } from "./components/Responsive";