@mohasinac/appkit 3.6.5 → 3.8.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 (298) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +17 -3
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +7 -2
  3. package/dist/_internal/client/features/tour/TourProvider.d.ts +5 -2
  4. package/dist/_internal/client/features/tour/TourProvider.js +125 -12
  5. package/dist/_internal/client/theme/ThemeProvider.js +1 -1
  6. package/dist/_internal/server/features/categories/data.js +2 -2
  7. package/dist/_internal/server/features/faqs/og.js +5 -1
  8. package/dist/_internal/server/features/reviews/og.js +5 -1
  9. package/dist/_internal/server/features/seo/manifest.js +2 -1
  10. package/dist/_internal/server/features/seo/og.js +7 -1
  11. package/dist/_internal/server/features/tester/visibility.d.ts +13 -0
  12. package/dist/_internal/server/features/tester/visibility.js +28 -0
  13. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  14. package/dist/_internal/server/functions/scheduled.js +9 -1
  15. package/dist/_internal/server/jobs/core/jobRunners.js +5 -0
  16. package/dist/_internal/server/jobs/core/resetOtpVerification.d.ts +17 -0
  17. package/dist/_internal/server/jobs/core/resetOtpVerification.js +88 -0
  18. package/dist/_internal/server/jobs/core/testerSandboxCleanup.d.ts +6 -0
  19. package/dist/_internal/server/jobs/core/testerSandboxCleanup.js +35 -0
  20. package/dist/_internal/server/jobs/handlers/_helpers.d.ts +6 -0
  21. package/dist/_internal/server/jobs/handlers/_helpers.js +12 -0
  22. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  23. package/dist/_internal/server/jobs/handlers/index.js +2 -0
  24. package/dist/_internal/server/jobs/handlers/messages.d.ts +2 -0
  25. package/dist/_internal/server/jobs/handlers/messages.js +2 -0
  26. package/dist/_internal/server/jobs/handlers/testerSandboxCleanup.d.ts +2 -0
  27. package/dist/_internal/server/jobs/handlers/testerSandboxCleanup.js +2 -0
  28. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  29. package/dist/_internal/shared/actions/action-registry.js +56 -0
  30. package/dist/_internal/shared/tokens/index.d.ts +12 -12
  31. package/dist/client.d.ts +15 -3
  32. package/dist/client.js +10 -2
  33. package/dist/constants/api-endpoints.d.ts +39 -12
  34. package/dist/constants/api-endpoints.js +17 -8
  35. package/dist/constants/field-names.d.ts +9 -0
  36. package/dist/constants/field-names.js +12 -0
  37. package/dist/constants/index.d.ts +1 -1
  38. package/dist/constants/index.js +1 -1
  39. package/dist/features/account/components/LinkedAccountsSection.d.ts +11 -0
  40. package/dist/features/account/components/LinkedAccountsSection.js +11 -0
  41. package/dist/features/account/components/UserSidebar.d.ts +3 -1
  42. package/dist/features/account/components/UserSidebar.js +9 -13
  43. package/dist/features/account/hooks/useCollapsedSections.d.ts +20 -0
  44. package/dist/features/account/hooks/useCollapsedSections.js +63 -0
  45. package/dist/features/account/hooks/useProfile.d.ts +8 -0
  46. package/dist/features/account/index.d.ts +1 -0
  47. package/dist/features/account/index.js +1 -0
  48. package/dist/features/admin/components/AdminAddressEditorView.js +2 -2
  49. package/dist/features/admin/components/AdminBidsView.js +6 -6
  50. package/dist/features/admin/components/AdminBrandsView.js +2 -2
  51. package/dist/features/admin/components/AdminCarouselView.js +2 -2
  52. package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
  53. package/dist/features/admin/components/AdminPrizeDrawsView.js +3 -3
  54. package/dist/features/admin/components/AdminProductEditorView.js +5 -2
  55. package/dist/features/admin/components/AdminReviewsView.js +5 -5
  56. package/dist/features/admin/components/AdminSectionsView.js +3 -18
  57. package/dist/features/admin/components/AdminSidebar.js +8 -6
  58. package/dist/features/admin/components/AdminSiteSettingsView.js +133 -127
  59. package/dist/features/admin/components/AdminSublistingCategoriesView.js +1 -1
  60. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.d.ts +9 -0
  61. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +129 -0
  62. package/dist/features/admin/components/AdminTesterChecklistView.d.ts +6 -0
  63. package/dist/features/admin/components/AdminTesterChecklistView.js +93 -0
  64. package/dist/features/admin/components/AdminUserEditorView.d.ts +3 -1
  65. package/dist/features/admin/components/AdminUserEditorView.js +7 -1
  66. package/dist/features/admin/components/AdminUsersView.js +1 -1
  67. package/dist/features/admin/components/DataListingView.js +2 -2
  68. package/dist/features/admin/components/analytics/AdminPageViewsReportView.d.ts +8 -0
  69. package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +41 -0
  70. package/dist/features/admin/components/index.d.ts +6 -0
  71. package/dist/features/admin/components/index.js +3 -0
  72. package/dist/features/admin/schemas/firestore.d.ts +0 -7
  73. package/dist/features/admin/schemas/firestore.js +6 -6
  74. package/dist/features/analytics/components/PageViewTracker.d.ts +12 -0
  75. package/dist/features/analytics/components/PageViewTracker.js +22 -0
  76. package/dist/features/analytics/repository/page-views.repository.d.ts +32 -0
  77. package/dist/features/analytics/repository/page-views.repository.js +43 -0
  78. package/dist/features/analytics/types.d.ts +6 -0
  79. package/dist/features/analytics/types.js +13 -0
  80. package/dist/features/auth/components/SocialAuthButtons.js +1 -1
  81. package/dist/features/auth/hooks/useAuth.d.ts +12 -0
  82. package/dist/features/auth/hooks/useAuth.js +109 -0
  83. package/dist/features/auth/permissions/constants.d.ts +1 -1
  84. package/dist/features/auth/repository/session.repository.d.ts +2 -0
  85. package/dist/features/auth/repository/session.repository.js +4 -1
  86. package/dist/features/auth/schemas/firestore.d.ts +17 -1
  87. package/dist/features/auth/schemas/firestore.js +2 -0
  88. package/dist/features/blog/components/BlogIndexListing.js +2 -2
  89. package/dist/features/blog/schemas/firestore.d.ts +4 -0
  90. package/dist/features/cart/actions/cart-actions.js +20 -2
  91. package/dist/features/categories/api/route.js +2 -2
  92. package/dist/features/categories/components/CategoriesIndexListing.js +3 -3
  93. package/dist/features/categories/components/CategoryBundlesListing.js +2 -2
  94. package/dist/features/categories/components/CategoryDetailPageView.js +3 -1
  95. package/dist/features/categories/components/CategoryProductsListing.js +2 -2
  96. package/dist/features/categories/schemas/firestore.d.ts +4 -0
  97. package/dist/features/classified/components/ClassifiedIndexListing.js +2 -2
  98. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +2 -2
  99. package/dist/features/email/primitives.d.ts +2 -2
  100. package/dist/features/email/primitives.js +2 -2
  101. package/dist/features/events/components/EventsIndexListing.js +2 -2
  102. package/dist/features/events/repository/event-entry.repository.js +1 -0
  103. package/dist/features/events/schemas/firestore.d.ts +7 -1
  104. package/dist/features/events/schemas/firestore.js +1 -0
  105. package/dist/features/layout/BackToTop.d.ts +6 -1
  106. package/dist/features/layout/BackToTop.js +31 -6
  107. package/dist/features/layout/BottomNavbar.js +1 -1
  108. package/dist/features/layout/NavItem.js +1 -1
  109. package/dist/features/layout/NavbarLayout.js +2 -2
  110. package/dist/features/live/components/LiveItemsIndexListing.js +2 -2
  111. package/dist/features/media/MediaVideo.js +5 -1
  112. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +2 -2
  113. package/dist/features/products/components/AuctionsIndexListing.js +2 -2
  114. package/dist/features/products/components/PrizeDrawsIndexListing.js +2 -2
  115. package/dist/features/products/components/ProductsIndexListing.js +2 -2
  116. package/dist/features/products/constants/action-defs.d.ts +2 -0
  117. package/dist/features/products/constants/action-defs.js +2 -0
  118. package/dist/features/products/constants/sieve.d.ts +0 -6
  119. package/dist/features/products/constants/sieve.js +4 -2
  120. package/dist/features/products/repository/products.repository.d.ts +20 -0
  121. package/dist/features/products/repository/products.repository.js +5 -0
  122. package/dist/features/products/schemas/firestore.d.ts +4 -0
  123. package/dist/features/promotions/components/CouponsIndexListing.js +18 -5
  124. package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
  125. package/dist/features/search/hooks/useNavSuggestions.js +20 -1
  126. package/dist/features/seller/actions/seller-actions.js +11 -6
  127. package/dist/features/seller/components/SellerAddressesView.js +2 -2
  128. package/dist/features/seller/components/SellerBidsView.js +2 -2
  129. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  130. package/dist/features/seller/components/SellerOrdersView.js +2 -2
  131. package/dist/features/seller/components/SellerProductsView.js +2 -2
  132. package/dist/features/seller/components/SellerSidebar.d.ts +3 -1
  133. package/dist/features/seller/components/SellerSidebar.js +9 -8
  134. package/dist/features/seller/components/SellerStoreCategoriesView.js +2 -2
  135. package/dist/features/seller/components/SellerTemplatesView.js +2 -2
  136. package/dist/features/shell/StepForm.js +4 -4
  137. package/dist/features/stores/actions/store-query-actions.d.ts +5 -4
  138. package/dist/features/stores/actions/store-query-actions.js +11 -8
  139. package/dist/features/stores/components/StoreAuctionsListing.js +2 -2
  140. package/dist/features/stores/components/StoreClassifiedsListing.js +2 -2
  141. package/dist/features/stores/components/StoreDetailLayoutView.js +1 -1
  142. package/dist/features/stores/components/StoreDigitalCodesListing.js +2 -2
  143. package/dist/features/stores/components/StoreLiveItemsListing.js +2 -2
  144. package/dist/features/stores/components/StorePreOrdersListing.js +2 -2
  145. package/dist/features/stores/components/StoreProductsListing.js +2 -2
  146. package/dist/features/stores/components/StoreReviewsListing.js +2 -2
  147. package/dist/features/stores/components/StoresIndexListing.js +2 -2
  148. package/dist/features/stores/repository/store.repository.js +3 -0
  149. package/dist/features/stores/schemas/firestore.d.ts +4 -0
  150. package/dist/features/tester/actions/checklist-item-actions.d.ts +69 -0
  151. package/dist/features/tester/actions/checklist-item-actions.js +42 -0
  152. package/dist/features/tester/actions/index.d.ts +1 -0
  153. package/dist/features/tester/actions/index.js +1 -0
  154. package/dist/features/tester/components/AdminTesterFeedbackIssuesView.d.ts +2 -0
  155. package/dist/features/tester/components/AdminTesterFeedbackIssuesView.js +22 -0
  156. package/dist/features/tester/components/AdminTesterFeedbackListView.d.ts +3 -0
  157. package/dist/features/tester/components/AdminTesterFeedbackListView.js +100 -0
  158. package/dist/features/tester/components/AdminTesterFeedbackReportView.d.ts +2 -0
  159. package/dist/features/tester/components/AdminTesterFeedbackReportView.js +30 -0
  160. package/dist/features/tester/components/AdminTesterFeedbackView.d.ts +2 -0
  161. package/dist/features/tester/components/AdminTesterFeedbackView.js +29 -0
  162. package/dist/features/tester/components/TesterChecklistStepRow.d.ts +18 -0
  163. package/dist/features/tester/components/TesterChecklistStepRow.js +29 -0
  164. package/dist/features/tester/components/TesterFeedbackChart.d.ts +14 -0
  165. package/dist/features/tester/components/TesterFeedbackChart.js +18 -0
  166. package/dist/features/tester/components/TesterHubView.d.ts +5 -0
  167. package/dist/features/tester/components/TesterHubView.js +71 -0
  168. package/dist/features/tester/components/index.d.ts +11 -0
  169. package/dist/features/tester/components/index.js +7 -0
  170. package/dist/features/tester/index.d.ts +2 -0
  171. package/dist/features/tester/index.js +2 -0
  172. package/dist/features/tester/repository/index.d.ts +2 -0
  173. package/dist/features/tester/repository/index.js +2 -0
  174. package/dist/features/tester/repository/tester-checklist-item.repository.d.ts +13 -0
  175. package/dist/features/tester/repository/tester-checklist-item.repository.js +55 -0
  176. package/dist/features/tester/repository/tester-checklist-response.repository.d.ts +50 -0
  177. package/dist/features/tester/repository/tester-checklist-response.repository.js +196 -0
  178. package/dist/features/tester/schemas/firestore.d.ts +85 -0
  179. package/dist/features/tester/schemas/firestore.js +93 -0
  180. package/dist/features/tester/schemas/index.d.ts +1 -0
  181. package/dist/features/tester/schemas/index.js +1 -0
  182. package/dist/features/tester/seed-data/blog-tester-seed-data.d.ts +2 -0
  183. package/dist/features/tester/seed-data/blog-tester-seed-data.js +40 -0
  184. package/dist/features/tester/seed-data/categories-tester-seed-data.d.ts +2 -0
  185. package/dist/features/tester/seed-data/categories-tester-seed-data.js +177 -0
  186. package/dist/features/tester/seed-data/events-tester-seed-data.d.ts +2 -0
  187. package/dist/features/tester/seed-data/events-tester-seed-data.js +50 -0
  188. package/dist/features/tester/seed-data/index.d.ts +6 -0
  189. package/dist/features/tester/seed-data/index.js +6 -0
  190. package/dist/features/tester/seed-data/products-tester-seed-data.d.ts +2 -0
  191. package/dist/features/tester/seed-data/products-tester-seed-data.js +151 -0
  192. package/dist/features/tester/seed-data/stores-tester-seed-data.d.ts +2 -0
  193. package/dist/features/tester/seed-data/stores-tester-seed-data.js +40 -0
  194. package/dist/features/tester/seed-data/tester-checklist-seed-data.d.ts +2 -0
  195. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +248 -0
  196. package/dist/features/tester/seed-data/tester-ttl.d.ts +4 -0
  197. package/dist/features/tester/seed-data/tester-ttl.js +6 -0
  198. package/dist/features/tester/server.d.ts +9 -0
  199. package/dist/features/tester/server.js +8 -0
  200. package/dist/index.d.ts +28 -2
  201. package/dist/index.js +51 -1
  202. package/dist/next/api/api-response.js +5 -1
  203. package/dist/next/api/routeHandler.js +10 -1
  204. package/dist/next/middleware/chain.js +1 -1
  205. package/dist/next/routing/route-map.d.ts +6 -7
  206. package/dist/next/routing/route-map.js +3 -7
  207. package/dist/providers/payment-manual/index.d.ts +2 -2
  208. package/dist/providers/payment-manual/index.js +2 -2
  209. package/dist/react/contexts/SessionContext.d.ts +4 -0
  210. package/dist/react/contexts/SessionContext.js +4 -0
  211. package/dist/repositories/index.d.ts +4 -0
  212. package/dist/repositories/index.js +3 -0
  213. package/dist/security/pii-encrypt.js +12 -2
  214. package/dist/seed/addresses-seed-data.js +1 -1
  215. package/dist/seed/bids-seed-data.js +64 -185
  216. package/dist/seed/blog-posts-seed-data.js +1 -1
  217. package/dist/seed/carousel-slides-seed-data.js +22 -16
  218. package/dist/seed/carousels-seed-data.js +1 -1
  219. package/dist/seed/cart-seed-data.js +1 -1
  220. package/dist/seed/categories-seed-data.js +1 -1
  221. package/dist/seed/claimed-coupons-seed-data.js +1 -1
  222. package/dist/seed/conversations-seed-data.js +1 -1
  223. package/dist/seed/coupon-usage-seed-data.js +1 -1
  224. package/dist/seed/coupons-seed-data.js +1 -1
  225. package/dist/seed/events-seed-data.js +1 -1
  226. package/dist/seed/faq-seed-data.js +119 -3
  227. package/dist/seed/grouped-listings-seed-data.d.ts +2 -0
  228. package/dist/seed/grouped-listings-seed-data.js +1 -1
  229. package/dist/seed/history-seed-data.js +1 -1
  230. package/dist/seed/homepage-sections-seed-data.js +1 -1
  231. package/dist/seed/index.d.ts +2 -2
  232. package/dist/seed/index.js +7 -3
  233. package/dist/seed/lottery-entries-seed-data.js +1 -1
  234. package/dist/seed/manifest.d.ts +4 -3
  235. package/dist/seed/manifest.js +13 -6
  236. package/dist/seed/notifications-seed-data.js +1 -1
  237. package/dist/seed/offers-seed-data.js +1 -1
  238. package/dist/seed/orders-seed-data.js +1 -1
  239. package/dist/seed/payouts-seed-data.js +1 -1
  240. package/dist/seed/products-art-seed-data.js +1 -1
  241. package/dist/seed/products-auctions-seed-data.js +1 -1
  242. package/dist/seed/products-classifieds-seed-data.js +1 -1
  243. package/dist/seed/products-digital-codes-seed-data.js +1 -1
  244. package/dist/seed/products-live-items-seed-data.js +1 -1
  245. package/dist/seed/products-preorders-seed-data.d.ts +2 -0
  246. package/dist/seed/products-preorders-seed-data.js +1 -1
  247. package/dist/seed/products-prize-draws-seed-data.js +1 -1
  248. package/dist/seed/products-standard-seed-data.js +1 -1
  249. package/dist/seed/products-stickers-seed-data.js +1 -1
  250. package/dist/seed/reviews-seed-data.js +1 -1
  251. package/dist/seed/scammers-seed-data.js +1 -1
  252. package/dist/seed/sessions-seed-data.js +1 -1
  253. package/dist/seed/site-settings-seed-data.js +22 -16
  254. package/dist/seed/store-addresses-seed-data.js +1 -1
  255. package/dist/seed/store-extensions-seed-data.js +1 -1
  256. package/dist/seed/stores-seed-data.js +1 -1
  257. package/dist/seed/support-tickets-seed-data.js +1 -1
  258. package/dist/seed/tester-checklist-seed-data.d.ts +2 -0
  259. package/dist/seed/tester-checklist-seed-data.js +248 -0
  260. package/dist/seed/users-seed-data.js +1 -1
  261. package/dist/seed/wishlists-seed-data.js +1 -1
  262. package/dist/server.d.ts +7 -2
  263. package/dist/server.js +19 -12
  264. package/dist/styles.css +181 -165
  265. package/dist/tailwind-utilities.css +1 -1
  266. package/dist/tokens/color-pairs.d.ts +46 -0
  267. package/dist/tokens/color-pairs.js +93 -0
  268. package/dist/tokens/index.d.ts +60 -60
  269. package/dist/tokens/index.js +30 -30
  270. package/dist/tokens/themes/cobalt-night.d.ts +3 -2
  271. package/dist/tokens/themes/cobalt-night.js +3 -2
  272. package/dist/tokens/themes/default-dark.d.ts +4 -1
  273. package/dist/tokens/themes/default-dark.js +53 -50
  274. package/dist/tokens/themes/default-light.d.ts +5 -1
  275. package/dist/tokens/themes/default-light.js +48 -44
  276. package/dist/tokens/themes/sunset.js +4 -4
  277. package/dist/tokens/tokens.css +128 -122
  278. package/dist/ui/components/CollapsibleSection.d.ts +15 -0
  279. package/dist/ui/components/CollapsibleSection.js +13 -0
  280. package/dist/ui/components/ListingToolbar.js +3 -2
  281. package/dist/ui/components/Semantic.style.css +3 -3
  282. package/dist/ui/components/SideDrawer.style.css +19 -19
  283. package/dist/ui/components/Slider.js +1 -1
  284. package/dist/ui/components/StickyToolbar.d.ts +36 -7
  285. package/dist/ui/components/StickyToolbar.js +63 -5
  286. package/dist/ui/components/Tabs.js +17 -1
  287. package/dist/ui/components/Tabs.style.css +10 -0
  288. package/dist/ui/components/Typography.js +7 -0
  289. package/dist/ui/components/surface-tokens.d.ts +0 -7
  290. package/dist/ui/components/surface-tokens.js +7 -0
  291. package/dist/ui/index.d.ts +6 -0
  292. package/dist/ui/index.js +3 -0
  293. package/dist/ui/rich-text/RichText.style.css +20 -20
  294. package/dist/utils/id-generators.d.ts +13 -0
  295. package/dist/utils/id-generators.js +17 -0
  296. package/package.json +1 -1
  297. package/scripts/seed-cli-loader.mjs +15 -0
  298. package/scripts/seed-cli.mjs +71 -17
@@ -53,9 +53,9 @@
53
53
  height: 3px;
54
54
  background: linear-gradient(
55
55
  to right,
56
- var(--appkit-color-primary-700, #1343de) 0%,
57
- var(--appkit-color-cobalt, #3570fc) 55%,
58
- var(--appkit-color-secondary-400, #84e122) 100%
56
+ var(--appkit-color-primary-700) 0%,
57
+ var(--appkit-color-primary) 55%,
58
+ var(--appkit-color-secondary-400) 100%
59
59
  );
60
60
  pointer-events: none;
61
61
  }
@@ -69,42 +69,42 @@
69
69
  border-color: var(--appkit-color-border);
70
70
  }
71
71
 
72
- /* create — soft blue-to-lime wash, echoes the wordmark gradient */
72
+ /* create — soft primary-to-secondary wash, echoes the wordmark gradient */
73
73
  .appkit-side-drawer__header--create {
74
74
  background: linear-gradient(
75
75
  135deg,
76
- rgba(19, 67, 222, 0.07) 0%,
77
- rgba(53, 112, 252, 0.05) 55%,
78
- rgba(132, 225, 34, 0.04) 100%
76
+ color-mix(in srgb, var(--appkit-color-primary) 7%, transparent) 0%,
77
+ color-mix(in srgb, var(--appkit-color-primary) 5%, transparent) 55%,
78
+ color-mix(in srgb, var(--appkit-color-secondary) 4%, transparent) 100%
79
79
  );
80
- border-color: rgba(53, 112, 252, 0.2);
80
+ border-color: color-mix(in srgb, var(--appkit-color-primary) 20%, transparent);
81
81
  }
82
82
  :is(.dark) .appkit-side-drawer__header--create {
83
83
  background: linear-gradient(
84
84
  135deg,
85
- rgba(19, 67, 222, 0.18) 0%,
86
- rgba(53, 112, 252, 0.12) 55%,
87
- rgba(132, 225, 34, 0.06) 100%
85
+ color-mix(in srgb, var(--appkit-color-primary) 18%, transparent) 0%,
86
+ color-mix(in srgb, var(--appkit-color-primary) 12%, transparent) 55%,
87
+ color-mix(in srgb, var(--appkit-color-secondary) 6%, transparent) 100%
88
88
  );
89
- border-color: rgba(53, 112, 252, 0.25);
89
+ border-color: color-mix(in srgb, var(--appkit-color-primary) 25%, transparent);
90
90
  }
91
91
 
92
- /* edit — warmer blue wash */
92
+ /* edit — warmer primary wash */
93
93
  .appkit-side-drawer__header--edit {
94
94
  background: linear-gradient(
95
95
  135deg,
96
- rgba(53, 112, 252, 0.06) 0%,
97
- rgba(132, 225, 34, 0.04) 100%
96
+ color-mix(in srgb, var(--appkit-color-primary) 6%, transparent) 0%,
97
+ color-mix(in srgb, var(--appkit-color-secondary) 4%, transparent) 100%
98
98
  );
99
- border-color: rgba(53, 112, 252, 0.15);
99
+ border-color: color-mix(in srgb, var(--appkit-color-primary) 15%, transparent);
100
100
  }
101
101
  :is(.dark) .appkit-side-drawer__header--edit {
102
102
  background: linear-gradient(
103
103
  135deg,
104
- rgba(53, 112, 252, 0.14) 0%,
105
- rgba(132, 225, 34, 0.06) 100%
104
+ color-mix(in srgb, var(--appkit-color-primary) 14%, transparent) 0%,
105
+ color-mix(in srgb, var(--appkit-color-secondary) 6%, transparent) 100%
106
106
  );
107
- border-color: rgba(53, 112, 252, 0.2);
107
+ border-color: color-mix(in srgb, var(--appkit-color-primary) 20%, transparent);
108
108
  }
109
109
 
110
110
  .appkit-side-drawer__header--delete {
@@ -28,7 +28,7 @@ export function Slider({ value: controlledValue, defaultValue = 0, min = 0, max
28
28
  "pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2 overflow-hidden rounded-full bg-zinc-200 bg-[var(--appkit-color-border)]",
29
29
  SIZE_CLASSES[size],
30
30
  ].join(" "), "data-section": "slider-div-610", children: _jsx("div", { className: [
31
- "h-full rounded-full bg-lime-600 dark:bg-pink-500",
31
+ "h-full rounded-full bg-primary",
32
32
  SIZE_CLASSES[size],
33
33
  ].join(" "), style: { width: `${Math.max(0, Math.min(100, percentage))}%` } }) }), _jsx("input", { id: inputId, type: "range", min: min, max: max, step: step, value: value, disabled: disabled, onChange: handleChange, onMouseUp: handleChangeEnd,
34
34
  // audit-touch-handler-ok: native <input type="range"> owns its own
@@ -1,15 +1,24 @@
1
- import type { ReactNode } from "react";
1
+ import { type ReactNode } from "react";
2
2
  /**
3
3
  * StickyToolbar — primitive for the recurrent translucent sticky bar pattern
4
4
  * (`sticky top-[calc(var(--header-height,0px)+var(--appkit-navbar-height,2.5rem))]
5
5
  * z-10 ... backdrop-blur-sm border-b ...`) used by search-results pages,
6
- * leaderboards, etc.
6
+ * leaderboards, sticky pagination rows, etc.
7
7
  *
8
8
  * The header offset is sourced from `--header-height`, which the global
9
9
  * AppLayoutShell sets at runtime. Consumer code never authors the offset
10
10
  * manually — only `audit-sticky-offsets` allowlisted files may.
11
+ *
12
+ * Dismiss/hide: pass `dismissible` (with a stable `id`) to let the user
13
+ * collapse the bar to a thin re-expand strip for the rest of the browser
14
+ * session — a viewport-annoyance-avoidance toggle, not a durable
15
+ * preference, so it resets on reload rather than persisting forever. This
16
+ * is what closes the mobile-overlap complaint the sticky toolbar pattern
17
+ * caused across listing pages: at narrow widths, any sticky bar competing
18
+ * with page content for vertical space needs a way out that doesn't require
19
+ * scrolling past it.
11
20
  */
12
- export type StickyToolbarOffset = "header" | "header+nav" | number;
21
+ export type StickyToolbarOffset = "header" | "header+nav" | "header+pagination" | "header+bulk-actions" | number;
13
22
  export type StickyToolbarTone = "default" | "muted" | "translucent" | "inverse";
14
23
  export type StickyToolbarPadding = "none" | "sm" | "md" | "lg" | "toolbar";
15
24
  export interface StickyToolbarProps {
@@ -20,11 +29,31 @@ export interface StickyToolbarProps {
20
29
  tone?: StickyToolbarTone;
21
30
  /** Show a bottom border. Default `true`. */
22
31
  border?: boolean;
23
- /** Padding preset. Default `"toolbar"`. */
32
+ /** Padding preset. Default `"toolbar"`. Use `"none"` + `className` for a responsive/custom padding a preset can't express. */
24
33
  padding?: StickyToolbarPadding;
25
- /** Stacking layer. Default `"above-content"` (z-10). */
26
- z?: "below-modal" | "above-content";
34
+ /**
35
+ * Stacking layer. Default `"above-content"` (z-10). Use `"above-toolbar"`
36
+ * (z-20) for a bar that must stack above another StickyToolbar beneath it
37
+ * — the common case being a bulk-action bar or primary filter toolbar
38
+ * sitting above a secondary sticky pagination row.
39
+ */
40
+ z?: "below-modal" | "above-content" | "above-toolbar";
27
41
  /** Accessible role override. */
28
42
  role?: string;
43
+ /** Extra classes appended after the primitive's own — the escape hatch for another primitive (e.g. ListingToolbar) built on top of this one. */
44
+ className?: string;
45
+ /** Forwarded to the root element — for `data-testid` and similar test/analytics hooks. */
46
+ dataTestId?: string;
47
+ /**
48
+ * When true, renders a collapse/expand control. Requires `id` — the
49
+ * collapsed state is stored in `sessionStorage` keyed by it, so distinct
50
+ * toolbars on the same page (or the same toolbar across route changes
51
+ * within a session) don't clobber each other.
52
+ */
53
+ dismissible?: boolean;
54
+ /** Required when `dismissible` is true — see above. */
55
+ id?: string;
56
+ /** Accessible label for the collapse/expand button. Default "Toolbar". */
57
+ label?: string;
29
58
  }
30
- export declare function StickyToolbar({ children, offset, tone, border, padding, z, role, }: StickyToolbarProps): import("react").JSX.Element;
59
+ export declare function StickyToolbar({ children, offset, tone, border, padding, z, role, className, dataTestId, dismissible, id, label, }: StickyToolbarProps): import("react").JSX.Element;
@@ -1,4 +1,7 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ "use client";
2
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { normalizeError } from "../../errors/normalize";
2
5
  const TONE_CLS = {
3
6
  default: "bg-[var(--appkit-color-surface)]",
4
7
  muted: "bg-[var(--appkit-color-bg)]",
@@ -19,19 +22,74 @@ function resolveOffsetClass(offset) {
19
22
  if (offset === "header+nav") {
20
23
  return "top-[calc(var(--header-height,0px)+var(--appkit-navbar-height,2.5rem))]";
21
24
  }
25
+ if (offset === "header+pagination") {
26
+ // Matches the sticky pagination-row offset repeated verbatim across
27
+ // every DataListingView-style index listing (44px = the fixed toolbar
28
+ // row height above it) — consolidated here instead of copy-pasted.
29
+ return "top-[calc(var(--header-height,0px)+44px)]";
30
+ }
31
+ if (offset === "header+bulk-actions") {
32
+ // Matches the sticky bulk-action-bar offset that stacks below both the
33
+ // filter toolbar (44px) and the pagination row above it (88px total).
34
+ return "top-[calc(var(--header-height,0px)+88px)]";
35
+ }
22
36
  // Numeric offsets are applied via inline style instead (see below) —
23
37
  // Tailwind's static scanner can never see a dynamically-interpolated
24
38
  // `top-[${offset}px]` arbitrary value, so no CSS rule would ever be
25
39
  // generated for it in the compiled stylesheet.
26
40
  return "";
27
41
  }
28
- export function StickyToolbar({ children, offset = "header", tone = "translucent", border = true, padding = "toolbar", z = "above-content", role, }) {
42
+ const STORAGE_PREFIX = "appkit:sticky-toolbar-collapsed:";
43
+ function readCollapsed(id) {
44
+ if (typeof window === "undefined")
45
+ return false;
46
+ try {
47
+ return window.sessionStorage.getItem(STORAGE_PREFIX + id) === "1";
48
+ }
49
+ catch (_err) {
50
+ void normalizeError(_err);
51
+ return false;
52
+ }
53
+ }
54
+ function writeCollapsed(id, value) {
55
+ try {
56
+ if (value)
57
+ window.sessionStorage.setItem(STORAGE_PREFIX + id, "1");
58
+ else
59
+ window.sessionStorage.removeItem(STORAGE_PREFIX + id);
60
+ }
61
+ catch (_err) {
62
+ void normalizeError(_err);
63
+ // sessionStorage unavailable (private browsing, etc.) — collapse still
64
+ // works for the current render, just doesn't survive a re-mount.
65
+ }
66
+ }
67
+ export function StickyToolbar({ children, offset = "header", tone = "translucent", border = true, padding = "toolbar", z = "above-content", role, className, dataTestId, dismissible = false, id, label = "Toolbar", }) {
68
+ const [collapsed, setCollapsed] = useState(false);
69
+ useEffect(() => {
70
+ if (dismissible && id)
71
+ setCollapsed(readCollapsed(id));
72
+ }, [dismissible, id]);
29
73
  const offsetCls = resolveOffsetClass(offset);
30
74
  const offsetStyle = typeof offset === "number" ? { top: `${offset}px` } : undefined;
31
75
  const borderCls = border ? "border-b border-[var(--appkit-color-border)]" : "";
32
- const zCls = z === "above-content" ? "z-10" : "z-[5]";
33
- return (_jsx("div", { role: role, style: offsetStyle,
76
+ const zCls = z === "above-toolbar" ? "z-20" : z === "above-content" ? "z-10" : "z-[5]";
77
+ const toggle = () => {
78
+ const next = !collapsed;
79
+ setCollapsed(next);
80
+ if (id)
81
+ writeCollapsed(id, next);
82
+ };
83
+ if (dismissible && id && collapsed) {
84
+ return (_jsx("div", { "data-testid": dataTestId, style: offsetStyle, className: `sticky ${offsetCls} ${zCls} ${TONE_CLS[tone]} ${borderCls} flex justify-center`, children: _jsxs("button", { type: "button", onClick: toggle, "aria-label": `Show ${label}`, "aria-expanded": false, className: "px-4 py-0.5 text-[length:var(--appkit-text-xs)] text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text)]", children: ["\u2304 Show ", label] }) }));
85
+ }
86
+ return (_jsxs("div", { role: role, "data-testid": dataTestId, style: offsetStyle,
34
87
  // for the translucent sticky-toolbar pattern. The header offset is
35
88
  // sourced from --header-height (set by AppLayoutShell at runtime).
36
- className: `sticky ${offsetCls} ${zCls} ${TONE_CLS[tone]} ${borderCls} ${PADDING_CLS[padding]}`, children: children }));
89
+ // `relative` only when dismissible the absolutely-positioned toggle
90
+ // button anchors to it without disturbing the existing internal
91
+ // layout of `children` (each of the 27+ migrated call sites has its
92
+ // own Row/Div structure; a flex wrapper here would double-nest and
93
+ // risk breaking their centering).
94
+ className: `sticky ${offsetCls} ${zCls} ${TONE_CLS[tone]} ${borderCls} ${PADDING_CLS[padding]} ${dismissible ? "relative pr-8" : ""} ${className ?? ""}`, children: [children, dismissible && id && (_jsx("button", { type: "button", onClick: toggle, "aria-label": `Hide ${label}`, "aria-expanded": true, className: "absolute right-1.5 top-1/2 -translate-y-1/2 px-1.5 py-1 text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text)]", children: "\u2303" }))] }));
37
95
  }
@@ -1,11 +1,17 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { createContext, useContext, useMemo, useState } from "react";
3
+ import React, { createContext, useContext, useMemo, useState } from "react";
4
+ import { Select } from "./Select";
4
5
  const UI_TABS = {
5
6
  list: "appkit-tabs-list",
7
+ listDropdown: "appkit-tabs-list--dropdown",
6
8
  trigger: "appkit-tabs-trigger",
7
9
  content: "appkit-tabs-content",
8
10
  };
11
+ /** Past this many items, TabsList renders a <Select> dropdown instead of a
12
+ * horizontal row — a scrollable row of 6+ tabs is unreadable/unreachable on
13
+ * mobile widths. */
14
+ const TABS_DROPDOWN_THRESHOLD = 5;
9
15
  const TabsContext = createContext({
10
16
  active: "",
11
17
  setActive: () => { },
@@ -25,6 +31,16 @@ export function Tabs({ defaultValue = "", value, onChange, className = "", child
25
31
  return (_jsx(TabsContext.Provider, { value: contextValue, children: _jsx("div", { className: className, "data-section": "tabs-div-614", children: children }) }));
26
32
  }
27
33
  export function TabsList({ className = "", children }) {
34
+ const { active, setActive } = useContext(TabsContext);
35
+ const items = React.Children.toArray(children).filter((child) => React.isValidElement(child));
36
+ if (items.length > TABS_DROPDOWN_THRESHOLD) {
37
+ const options = items.map((item) => ({
38
+ value: item.props.value,
39
+ label: typeof item.props.children === "string" ? item.props.children : item.props.value,
40
+ disabled: item.props.disabled,
41
+ }));
42
+ return (_jsx(Select, { bare: true, "aria-label": "Tabs", role: "tablist", options: options, value: active, onValueChange: setActive, className: [UI_TABS.list, UI_TABS.listDropdown, className].filter(Boolean).join(" ") }));
43
+ }
28
44
  return (_jsx("div", { role: "tablist", className: [UI_TABS.list, className].filter(Boolean).join(" "), "data-section": "tabs-div-615", children: children }));
29
45
  }
30
46
  export function TabsTrigger({ value, disabled, className = "", children, }) {
@@ -14,6 +14,16 @@
14
14
  scrollbar-width: thin;
15
15
  }
16
16
 
17
+ /* Past TABS_DROPDOWN_THRESHOLD triggers, TabsList renders a <Select bare>
18
+ instead of the flex row above — override the row-specific layout rules
19
+ that don't apply to a native <select>. */
20
+ .appkit-tabs-list--dropdown {
21
+ display: block;
22
+ overflow: visible;
23
+ border-bottom: none;
24
+ max-width: 20rem;
25
+ }
26
+
17
27
  .appkit-tabs-trigger {
18
28
  margin-bottom: -1px;
19
29
  border-bottom: 2px solid transparent;
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from "react";
3
3
  import { ROUNDED_MAP, PADDING_MAP, X_ONLY_MAP } from "./surface-tokens";
4
+ import { getSurfaceTextClass } from "../../tokens/color-pairs";
4
5
  const TYPOGRAPHY = {
5
6
  headingLevel: {
6
7
  1: "appkit-heading--h1",
@@ -356,6 +357,11 @@ const SPAN_SHADOW_MAP = {
356
357
  };
357
358
  export const Span = React.forwardRef(function Span({ variant = "inherit", color, size, smSize, mdSize, lgSize, xlSize, weight, transform, truncate, numeric, italic, family, align, gradient, rounded, padding, surface, border, layout, gap, shadow, className = "", children, ...props }, ref) {
358
359
  const resolvedColor = color ?? variant;
360
+ // Colors as a function (appkit/src/tokens/color-pairs.ts): only fall back to
361
+ // the surface's paired default text color when the consumer hasn't already
362
+ // requested one explicitly (resolvedColor === "inherit", i.e. neither
363
+ // `color` nor `variant` was passed) — never fights an explicit choice.
364
+ const surfaceTextFallback = surface && resolvedColor === "inherit" ? getSurfaceTextClass(surface) : "";
359
365
  const classes = [
360
366
  "appkit-span",
361
367
  size ? TYPOGRAPHY.textSize[size] : "",
@@ -365,6 +371,7 @@ export const Span = React.forwardRef(function Span({ variant = "inherit", color,
365
371
  responsiveSizeClass("xl:", xlSize),
366
372
  weight ? TYPOGRAPHY.textWeight[weight] : "",
367
373
  TYPOGRAPHY.colorVariant[resolvedColor],
374
+ surfaceTextFallback,
368
375
  ...shapingClasses({ transform, truncate, numeric, italic, family, align, gradient }),
369
376
  rounded ? SPAN_ROUNDED_MAP[rounded] : "",
370
377
  padding ? SPAN_PADDING_MAP[padding] : "",
@@ -1,10 +1,3 @@
1
- /**
2
- * Surface & layout tokens — shared prop maps for all layout primitives.
3
- *
4
- * These maps power the Bootstrap/MUI-style props (`surface`, `padding`,
5
- * `rounded`, `border`, `shadow`) on Stack, Row, Grid, Container, Section,
6
- * Article, Main, Aside, Div, BlockHeader, and BlockFooter.
7
- */
8
1
  export declare const SURFACE_MAP: {
9
2
  readonly none: "";
10
3
  readonly default: "bg-[var(--appkit-color-surface)]";
@@ -5,6 +5,7 @@
5
5
  * `rounded`, `border`, `shadow`) on Stack, Row, Grid, Container, Section,
6
6
  * Article, Main, Aside, Div, BlockHeader, and BlockFooter.
7
7
  */
8
+ import { getSurfaceTextClass } from "../../tokens/color-pairs";
8
9
  export const SURFACE_MAP = {
9
10
  none: "",
10
11
  default: "bg-[var(--appkit-color-surface)]",
@@ -270,6 +271,12 @@ const OVERFLOW_MAP = {
270
271
  export function buildSurfaceClasses(props) {
271
272
  return [
272
273
  props.surface ? SURFACE_MAP[props.surface] : "",
274
+ // Colors as a function, not a convention (appkit/src/tokens/color-pairs.ts):
275
+ // every `surface` gets a readable default text color from here, resolved
276
+ // via getSurfaceTextClass — never picked independently. A child element's
277
+ // own explicit text color class still wins (normal CSS specificity), so
278
+ // this only fills in a floor, it never overrides an intentional choice.
279
+ props.surface ? getSurfaceTextClass(props.surface) : "",
273
280
  props.padding ? PADDING_MAP[props.padding] : "",
274
281
  props.paddingX ? X_ONLY_MAP[props.paddingX] : "",
275
282
  props.paddingY ? Y_ONLY_MAP[props.paddingY] : "",
@@ -222,3 +222,9 @@ export { Scrim } from "./components/Scrim";
222
222
  export type { ScrimProps, ScrimDirection, ScrimIntensity } from "./components/Scrim";
223
223
  export { Kbd } from "./components/Kbd";
224
224
  export type { KbdProps, KbdSize, KbdTone } from "./components/Kbd";
225
+ export { StickyToolbar } from "./components/StickyToolbar";
226
+ export type { StickyToolbarProps, StickyToolbarOffset, StickyToolbarTone, StickyToolbarPadding, } from "./components/StickyToolbar";
227
+ export { Show, Hide } from "./components/Responsive";
228
+ export type { ShowProps, HideProps } from "./components/Responsive";
229
+ export { CollapsibleSection } from "./components/CollapsibleSection";
230
+ export type { CollapsibleSectionProps } from "./components/CollapsibleSection";
package/dist/ui/index.js CHANGED
@@ -116,3 +116,6 @@ export { HorizontalRule } from "./components/HorizontalRule";
116
116
  export { Anchor } from "./components/Anchor";
117
117
  export { Scrim } from "./components/Scrim";
118
118
  export { Kbd } from "./components/Kbd";
119
+ export { StickyToolbar } from "./components/StickyToolbar";
120
+ export { Show, Hide } from "./components/Responsive";
121
+ export { CollapsibleSection } from "./components/CollapsibleSection";
@@ -56,14 +56,14 @@
56
56
  border-radius: 0.25rem;
57
57
  font-size: 0.875em;
58
58
  font-weight: 500;
59
- background-color: rgba(53, 112, 252, 0.08); /* primary cobalt /8 */
60
- color: #1343de; /* primary-700 cobalt */
61
- border: 1px solid rgba(53, 112, 252, 0.18);
59
+ background-color: color-mix(in srgb, var(--appkit-color-primary) 8%, transparent);
60
+ color: var(--appkit-color-primary-700);
61
+ border: 1px solid color-mix(in srgb, var(--appkit-color-primary) 18%, transparent);
62
62
  }
63
63
 
64
64
  .dark .appkit-rich-text :not(pre) > code {
65
65
  background-color: rgba(51, 65, 85, 0.6); /* slate-700/60 */
66
- color: #84e122; /* lime green — high contrast on dark */
66
+ color: var(--appkit-color-secondary-400);
67
67
  border-color: rgba(71, 85, 105, 0.5);
68
68
  }
69
69
 
@@ -86,31 +86,31 @@
86
86
 
87
87
  /* --- Blockquote ----------------------------------------------------------- */
88
88
  .appkit-rich-text blockquote {
89
- border-left: 3px solid #3570fc; /* primary cobalt */
89
+ border-left: 3px solid var(--appkit-color-primary);
90
90
  padding: 0.5rem 1rem;
91
91
  margin: 1.25rem 0;
92
92
  border-radius: 0 0.375rem 0.375rem 0;
93
- background-color: rgba(53, 112, 252, 0.06);
93
+ background-color: color-mix(in srgb, var(--appkit-color-primary) 6%, transparent);
94
94
  color: var(--appkit-color-zinc-700);
95
95
  font-style: italic;
96
96
  }
97
97
 
98
98
  .dark .appkit-rich-text blockquote {
99
- border-left-color: #f063b9; /* secondary-400 */
100
- background-color: rgba(240, 99, 185, 0.06);
99
+ border-left-color: var(--appkit-color-secondary-400);
100
+ background-color: color-mix(in srgb, var(--appkit-color-secondary) 6%, transparent);
101
101
  color: var(--appkit-color-text-faint);
102
102
  }
103
103
 
104
104
  /* --- Mark / Highlight ----------------------------------------------------- */
105
105
  .appkit-rich-text mark {
106
- background-color: rgba(101, 196, 8, 0.25);
106
+ background-color: color-mix(in srgb, var(--appkit-color-secondary) 25%, transparent);
107
107
  color: inherit;
108
108
  border-radius: 0.125rem;
109
109
  padding: 0 0.1em;
110
110
  }
111
111
 
112
112
  .dark .appkit-rich-text mark {
113
- background-color: rgba(101, 196, 8, 0.35);
113
+ background-color: color-mix(in srgb, var(--appkit-color-secondary) 35%, transparent);
114
114
  color: var(--appkit-color-zinc-100);
115
115
  }
116
116
 
@@ -128,26 +128,26 @@
128
128
 
129
129
  /* --- Links ---------------------------------------------------------------- */
130
130
  .appkit-rich-text a {
131
- color: #1a55f2; /* primary-600 cobalt */
131
+ color: var(--appkit-color-primary-600);
132
132
  text-decoration: underline;
133
- text-decoration-color: rgba(26, 85, 242, 0.6);
133
+ text-decoration-color: color-mix(in srgb, var(--appkit-color-primary-600) 60%, transparent);
134
134
  text-underline-offset: 2px;
135
135
  transition: color 150ms, text-decoration-color 150ms;
136
136
  }
137
137
 
138
138
  .appkit-rich-text a:hover {
139
- color: #1343de; /* primary-700 cobalt */
140
- text-decoration-color: rgba(19, 67, 222, 0.7);
139
+ color: var(--appkit-color-primary-700);
140
+ text-decoration-color: color-mix(in srgb, var(--appkit-color-primary-700) 70%, transparent);
141
141
  }
142
142
 
143
143
  .dark .appkit-rich-text a {
144
- color: #84e122; /* lime green — high contrast on dark bg */
145
- text-decoration-color: rgba(132, 225, 34, 0.6);
144
+ color: var(--appkit-color-secondary-400);
145
+ text-decoration-color: color-mix(in srgb, var(--appkit-color-secondary-400) 60%, transparent);
146
146
  }
147
147
 
148
148
  .dark .appkit-rich-text a:hover {
149
- color: #a3f550; /* lighter lime green */
150
- text-decoration-color: rgba(163, 245, 80, 0.6);
149
+ color: var(--appkit-color-secondary-300);
150
+ text-decoration-color: color-mix(in srgb, var(--appkit-color-secondary-300) 60%, transparent);
151
151
  }
152
152
 
153
153
  /* --- Tables --------------------------------------------------------------- */
@@ -274,11 +274,11 @@
274
274
  .appkit-rich-text ins {
275
275
  text-decoration: underline;
276
276
  text-decoration-style: wavy;
277
- text-decoration-color: #3570fc; /* primary cobalt */
277
+ text-decoration-color: var(--appkit-color-primary);
278
278
  }
279
279
 
280
280
  .dark .appkit-rich-text ins {
281
- text-decoration-color: #84e122; /* lime green on dark */
281
+ text-decoration-color: var(--appkit-color-secondary-400);
282
282
  }
283
283
 
284
284
  .appkit-rich-text del {
@@ -65,6 +65,13 @@ export interface GenerateFAQIdInput {
65
65
  customId?: string;
66
66
  }
67
67
  export declare function generateFAQId(input: GenerateFAQIdInput): string;
68
+ export interface GenerateChecklistItemIdInput {
69
+ groupKey: string;
70
+ pageKey: string;
71
+ label: string;
72
+ customId?: string;
73
+ }
74
+ export declare function generateChecklistItemId(input: GenerateChecklistItemIdInput): string;
68
75
  export declare function generateCouponId(code: string, customId?: string): string;
69
76
  export interface GenerateCarouselIdInput {
70
77
  title: string;
@@ -266,6 +273,12 @@ export type MediaFilenameContext = ({
266
273
  buyerName: string;
267
274
  ext?: string;
268
275
  date?: Date;
276
+ } | {
277
+ type: "tester-screenshot";
278
+ testerName: string;
279
+ checklistItemId: string;
280
+ ext?: string;
281
+ date?: Date;
269
282
  };
270
283
  export declare function generateMediaFilename(ctx: MediaFilenameContext): string;
271
284
  export declare function validateMediaFilename(filename: string): boolean;
@@ -77,6 +77,12 @@ export function generateFAQId(input) {
77
77
  const questionSlug = slugify(input.question).substring(0, 50).replace(/-+$/, "");
78
78
  return `faq-${slugify(input.category)}-${questionSlug}`;
79
79
  }
80
+ export function generateChecklistItemId(input) {
81
+ if (input.customId?.trim())
82
+ return input.customId.trim();
83
+ const labelSlug = slugify(input.label).substring(0, 40).replace(/-+$/, "");
84
+ return `checklist-${slugify(input.groupKey)}-${slugify(input.pageKey)}-${labelSlug}`;
85
+ }
80
86
  // ─── Coupon ───────────────────────────────────────────────────────────────────
81
87
  export function generateCouponId(code, customId) {
82
88
  if (customId?.trim())
@@ -425,6 +431,16 @@ export function generateMediaFilename(ctx) {
425
431
  const name = ctx.buyerName.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").slice(0, 20);
426
432
  return `payment-proof-${ctx.orderId}-${name}-${y}${m}${day}.${ext}`;
427
433
  }
434
+ case "tester-screenshot": {
435
+ const d = ctx.date ?? new Date();
436
+ const y = d.getFullYear();
437
+ const m = String(d.getMonth() + 1).padStart(2, "0");
438
+ const day = String(d.getDate()).padStart(2, "0");
439
+ const ext = ctx.ext ?? "jpg";
440
+ const name = ctx.testerName.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").slice(0, 20);
441
+ const item = ctx.checklistItemId.toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 40);
442
+ return `tester-screenshot-${item}-${name}-${y}${m}${day}.${ext}`;
443
+ }
428
444
  }
429
445
  }
430
446
  /**
@@ -475,6 +491,7 @@ const MEDIA_FILENAME_PATTERNS = [
475
491
  { context: "shipping-proof", pattern: new RegExp(`^shipping-proof-${SLUG_PART}-${DATE_PART}\\.${EXT_PART}$`) },
476
492
  { context: "refund-proof", pattern: new RegExp(`^refund-proof-${SLUG_PART}-${SLUG_PART}-${DATE_PART}\\.${EXT_PART}$`) },
477
493
  { context: "payment-proof", pattern: new RegExp(`^payment-proof-${SLUG_PART}-${SLUG_PART}-${DATE_PART}\\.${EXT_PART}$`) },
494
+ { context: "tester-screenshot", pattern: new RegExp(`^tester-screenshot-${SLUG_PART}-${SLUG_PART}-${DATE_PART}\\.${EXT_PART}$`) },
478
495
  ];
479
496
  export function validateMediaFilename(filename) {
480
497
  if (!filename || filename.length > 256)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohasinac/appkit",
3
- "version": "3.6.5",
3
+ "version": "3.8.0",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -11,6 +11,18 @@
11
11
  // `import "./foo.css"` side-effect statements that Node ESM can't load.
12
12
  const STUB_EXTENSIONS = [".css", ".scss", ".sass", ".png", ".jpg", ".jpeg", ".svg", ".webp", ".gif"];
13
13
 
14
+ // server-only / client-only are Next.js-specific sentinel packages — their
15
+ // entire module body unconditionally throws, because their whole purpose is
16
+ // a Next.js-compiler-time + Next.js-runtime guard against importing a
17
+ // server-only (or client-only) module from the wrong side of the boundary.
18
+ // A raw Node script (this CLI) is neither a Next.js Server Component nor a
19
+ // Client Component, so the guard is meaningless here — the main
20
+ // @mohasinac/appkit barrel transitively reaches a module (e.g.
21
+ // features/contact/email.tsx) that imports "server-only" at the top level,
22
+ // which crashes the whole CLI on load. Stub both to a no-op module. Found
23
+ // 2026-08-17 debugging the CLI seed tool being unable to import appkit at all.
24
+ const SENTINEL_SPECIFIERS = new Set(["server-only", "client-only"]);
25
+
14
26
  export async function load(url, context, nextLoad) {
15
27
  if (STUB_EXTENSIONS.some((ext) => url.endsWith(ext))) {
16
28
  return { format: "module", shortCircuit: true, source: "export default undefined;" };
@@ -19,6 +31,9 @@ export async function load(url, context, nextLoad) {
19
31
  }
20
32
 
21
33
  export async function resolve(specifier, context, nextResolve) {
34
+ if (SENTINEL_SPECIFIERS.has(specifier)) {
35
+ return { url: `data:text/javascript,export default undefined;`, shortCircuit: true };
36
+ }
22
37
  try {
23
38
  return await nextResolve(specifier, context);
24
39
  } catch (err) {