@mohasinac/appkit 4.69.1 → 4.71.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 (182) hide show
  1. package/PROVIDERS.md +190 -0
  2. package/dist/.build-stamp.json +3 -3
  3. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +2 -1
  4. package/dist/_internal/server/features/checkout/actions.js +43 -8
  5. package/dist/_internal/server/features/orders/actions.js +2 -1
  6. package/dist/_internal/server/features/orders/adapters.js +18 -0
  7. package/dist/_internal/server/features/orders/balance.js +2 -1
  8. package/dist/_internal/server/features/orders/cancellation-refund.d.ts +0 -89
  9. package/dist/_internal/server/features/orders/cancellation-refund.js +3 -2
  10. package/dist/_internal/server/features/payouts/actions.js +2 -1
  11. package/dist/_internal/server/features/points/award.js +3 -2
  12. package/dist/_internal/server/features/protection-claims/actions.js +2 -1
  13. package/dist/_internal/server/features/refunds/actions.js +3 -2
  14. package/dist/_internal/server/features/shipping/courier-block.js +5 -2
  15. package/dist/_internal/server/features/shipping/reconcile.js +3 -2
  16. package/dist/_internal/server/features/shipping/reimbursement.js +3 -2
  17. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  18. package/dist/_internal/server/features/stores/adapters.js +12 -2
  19. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +7 -3
  20. package/dist/_internal/server/jobs/core/emiInstallmentReminder.js +2 -1
  21. package/dist/_internal/server/jobs/core/obligationSweep.js +5 -4
  22. package/dist/_internal/server/jobs/core/onScamReportCreate.js +2 -1
  23. package/dist/_internal/server/jobs/core/paymentReconcile.js +5 -4
  24. package/dist/_internal/shared/checkout/rules/auction.rule.js +25 -7
  25. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +26 -8
  26. package/dist/_internal/shared/config/schema.d.ts +15 -0
  27. package/dist/_internal/shared/content/published-values.d.ts +2 -2
  28. package/dist/_internal/shared/content/published-values.js +31 -12
  29. package/dist/_internal/shared/features/auctions/errors.js +2 -1
  30. package/dist/_internal/shared/features/orders/refund-copy.js +3 -2
  31. package/dist/_internal/shared/features/promotions/errors.js +2 -1
  32. package/dist/constants/field-names.d.ts +23 -0
  33. package/dist/constants/field-names.js +23 -0
  34. package/dist/constants/storage-keys.d.ts +90 -0
  35. package/dist/constants/storage-keys.js +119 -0
  36. package/dist/contracts/index.d.ts +1 -1
  37. package/dist/contracts/payment.d.ts +42 -0
  38. package/dist/contracts/registry.d.ts +8 -0
  39. package/dist/contracts/tax.d.ts +118 -0
  40. package/dist/contracts/tax.js +3 -0
  41. package/dist/core/brand-resolver.d.ts +92 -0
  42. package/dist/core/brand-resolver.js +120 -0
  43. package/dist/core/brand-text.d.ts +15 -0
  44. package/dist/core/brand-text.js +73 -0
  45. package/dist/core/hooks/useNewsletterSubscribe.d.ts +30 -0
  46. package/dist/core/hooks/useNewsletterSubscribe.js +121 -0
  47. package/dist/features/about/components/DeveloperView.js +2 -1
  48. package/dist/features/about/index.d.ts +0 -2
  49. package/dist/features/about/index.js +0 -1
  50. package/dist/features/account/components/BuyerAccountGuideView.js +2 -1
  51. package/dist/features/account/components/BuyerAuctionsGuideView.js +4 -3
  52. package/dist/features/account/components/BuyerOrdersGuideView.js +6 -5
  53. package/dist/features/account/components/BuyerShoppingGuideView.js +3 -2
  54. package/dist/features/account/components/UserOffersPanel.js +2 -1
  55. package/dist/features/account/hooks/useCollapsedSections.js +5 -3
  56. package/dist/features/account/schemas/index.js +1 -1
  57. package/dist/features/admin/actions/notification-actions.js +9 -2
  58. package/dist/features/admin/components/AdminAnalyticsGuideView.js +2 -1
  59. package/dist/features/admin/components/AdminBundlesView.js +2 -1
  60. package/dist/features/admin/components/AdminCatalogGuideView.js +2 -1
  61. package/dist/features/admin/components/AdminContentGuideView.js +2 -1
  62. package/dist/features/admin/components/AdminFaqEditorView.js +2 -1
  63. package/dist/features/admin/components/AdminGatewayEventsView.js +2 -1
  64. package/dist/features/admin/components/AdminGuideHubView.js +2 -1
  65. package/dist/features/admin/components/AdminMoneyCasesView.js +2 -1
  66. package/dist/features/admin/components/AdminOrdersGuideView.js +2 -1
  67. package/dist/features/admin/components/AdminProductsView.js +3 -2
  68. package/dist/features/admin/components/AdminSectionsView.js +3 -2
  69. package/dist/features/admin/components/AdminSiteSettingsView.js +8 -7
  70. package/dist/features/admin/components/AdminStoresGuideView.js +2 -1
  71. package/dist/features/admin/components/AdminSupportTicketDetailView.js +2 -1
  72. package/dist/features/admin/components/AdminTeamGuideView.js +2 -1
  73. package/dist/features/admin/components/AdminTrustGuideView.js +3 -2
  74. package/dist/features/admin/components/AdminUsersGuideView.js +2 -1
  75. package/dist/features/admin/components/sections/adminSectionsTypes.js +1 -1
  76. package/dist/features/admin/schemas/firestore.js +0 -1
  77. package/dist/features/auth/actions/user-slug.js +21 -2
  78. package/dist/features/auth/hooks/useAuth.js +11 -4
  79. package/dist/features/cart/utils/pending-ops.js +16 -3
  80. package/dist/features/catalogue/utils/product-from-item.d.ts +18 -2
  81. package/dist/features/catalogue/utils/product-from-item.js +23 -4
  82. package/dist/features/categories/components/BundleItemsPicker.js +2 -1
  83. package/dist/features/categories/components/CategoryDetailPageView.js +2 -1
  84. package/dist/features/categories/components/ContextualTrail.d.ts +9 -2
  85. package/dist/features/categories/components/ContextualTrail.js +11 -3
  86. package/dist/features/categories/components/LastCategoryBeacon.js +2 -2
  87. package/dist/features/checkout/actions/checkout-value-otp-actions.js +9 -1
  88. package/dist/features/contact/email.js +11 -12
  89. package/dist/features/email/notification-templates.js +4 -5
  90. package/dist/features/email/render-static-markup.d.ts +34 -0
  91. package/dist/features/email/render-static-markup.js +4 -0
  92. package/dist/features/events/utils/event-charts.js +2 -1
  93. package/dist/features/homepage/components/AnnouncementBar.js +5 -3
  94. package/dist/features/homepage/components/FAQSection.js +1 -1
  95. package/dist/features/homepage/components/MarketplaceHomepageView.js +34 -0
  96. package/dist/features/homepage/components/WelcomeSection.d.ts +3 -1
  97. package/dist/features/homepage/components/WelcomeSection.js +2 -2
  98. package/dist/features/homepage/lib/section-renderer.d.ts +8 -0
  99. package/dist/features/homepage/lib/section-renderer.js +1 -1
  100. package/dist/features/layout/AppLayoutShell.d.ts +3 -1
  101. package/dist/features/layout/AppLayoutShell.js +2 -2
  102. package/dist/features/layout/TitleBarLayout.d.ts +8 -1
  103. package/dist/features/layout/TitleBarLayout.js +2 -2
  104. package/dist/features/media/MediaVideo.js +2 -1
  105. package/dist/features/orders/actions/refund-actions.js +3 -2
  106. package/dist/features/orders/components/RefundRequestView.js +15 -2
  107. package/dist/features/orders/repository/orders.repository.js +2 -1
  108. package/dist/features/orders/types/index.d.ts +14 -0
  109. package/dist/features/orders/utils/payment-proof-message.js +5 -2
  110. package/dist/features/price-index/components/PriceIndexToolView.js +6 -5
  111. package/dist/features/pricing/components/AdminPricingView.js +2 -1
  112. package/dist/features/print/components/labels.js +2 -1
  113. package/dist/features/products/components/CityCollectiblesView.js +2 -1
  114. package/dist/features/products/components/MakeOfferButton.js +2 -1
  115. package/dist/features/products/components/PrizeDrawCollage.js +3 -2
  116. package/dist/features/products/components/PrizeRevealModal.js +2 -1
  117. package/dist/features/products/repository/products.repository.js +2 -1
  118. package/dist/features/promotions/components/CouponCard.js +3 -2
  119. package/dist/features/promotions/components/CouponHelpDetails.js +2 -1
  120. package/dist/features/promotions/constants/coupon-help.d.ts +1 -1
  121. package/dist/features/promotions/constants/coupon-help.js +8 -1
  122. package/dist/features/scams/components/ScamAwarenessModal.js +2 -1
  123. package/dist/features/scams/components/ScamProfileView.js +5 -3
  124. package/dist/features/scams/components/ScamRegistryView.js +2 -1
  125. package/dist/features/scams/constants/scam-types.d.ts +13 -1
  126. package/dist/features/scams/constants/scam-types.js +67 -23
  127. package/dist/features/scams/schemas/firestore.js +1 -1
  128. package/dist/features/search/components/Search.js +5 -1
  129. package/dist/features/seller/actions/offer-actions.js +47 -9
  130. package/dist/features/seller/components/DispatchForm.js +3 -2
  131. package/dist/features/seller/components/PrintCenterView.js +4 -2
  132. package/dist/features/seller/components/SellerBundlesView.js +2 -1
  133. package/dist/features/seller/components/SellerPayoutSettingsView.js +3 -2
  134. package/dist/features/seller/components/SellerProductShell.js +3 -2
  135. package/dist/features/seller/components/SellerProductsView.js +4 -3
  136. package/dist/features/store-extensions/repository/store-extensions.repositories.d.ts +30 -4
  137. package/dist/features/store-extensions/repository/store-extensions.repositories.js +46 -7
  138. package/dist/features/store-extensions/schemas/firestore.d.ts +22 -3
  139. package/dist/features/store-extensions/schemas/firestore.js +20 -0
  140. package/dist/features/stores/components/StoreCapabilitiesGuideView.js +7 -6
  141. package/dist/features/stores/components/StoreFinanceGuideView.js +6 -5
  142. package/dist/features/stores/components/StoreGuideHubView.js +2 -1
  143. package/dist/features/stores/components/StoreListingsGuideView.js +2 -1
  144. package/dist/features/stores/components/StoreOrdersGuideView.js +5 -4
  145. package/dist/features/stores/components/StoreSettingsGuideView.js +2 -1
  146. package/dist/features/support/schemas/index.d.ts +2 -2
  147. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.d.ts +1 -1
  148. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +3 -2
  149. package/dist/features/whatsapp-bot/helpers/whatsapp.js +5 -2
  150. package/dist/index.d.ts +0 -3
  151. package/dist/index.js +0 -6
  152. package/dist/providers/payment-manual/index.d.ts +11 -0
  153. package/dist/providers/payment-manual/index.js +13 -0
  154. package/dist/providers/payment-phonepe/index.d.ts +23 -7
  155. package/dist/providers/payment-phonepe/index.js +15 -0
  156. package/dist/providers/payment-razorpay/index.d.ts +13 -0
  157. package/dist/providers/payment-razorpay/index.js +21 -1
  158. package/dist/providers/tax-india-gst/index.d.ts +45 -0
  159. package/dist/providers/tax-india-gst/index.js +78 -0
  160. package/dist/react/hooks/useScrollToTop.d.ts +5 -0
  161. package/dist/react/hooks/useScrollToTop.js +70 -0
  162. package/dist/schemas/registry.d.ts +2 -2
  163. package/dist/seo/json-ld.js +25 -4
  164. package/dist/styles.css +20 -0
  165. package/dist/ui/components/SiteLogo.d.ts +20 -2
  166. package/dist/ui/components/SiteLogo.js +28 -6
  167. package/dist/ui/components/SiteMark.d.ts +1 -1
  168. package/dist/ui/components/SiteMark.js +21 -6
  169. package/dist/ui/components/Tabs.d.ts +9 -1
  170. package/dist/ui/components/Tabs.js +20 -3
  171. package/dist/ui/components/Tabs.style.css +20 -0
  172. package/dist/ui/rich-text/RichText.d.ts +0 -12
  173. package/dist/ui/rich-text/RichText.js +52 -1
  174. package/dist/utils/date.formatter.d.ts +20 -0
  175. package/dist/utils/date.formatter.js +25 -0
  176. package/dist/utils/number.formatter.d.ts +47 -0
  177. package/dist/utils/number.formatter.js +79 -1
  178. package/dist/validation/phone.validator.d.ts +0 -1
  179. package/dist/validation/phone.validator.js +17 -3
  180. package/package.json +17 -3
  181. package/dist/features/about/components/AboutView.d.ts +0 -30
  182. package/dist/features/about/components/AboutView.js +0 -14
@@ -1,12 +1,23 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  /**
4
- * LetItRip site logo — SVG wordmark "LetItRip" + small ".in" superscript.
4
+ * Site logo — an SVG wordmark with an optional TLD badge.
5
+ *
6
+ * 🛑 The glyphs are the CONSUMER's. This header used to read "SVG wordmark
7
+ * LetItRip + small .in superscript", and that was an accurate description: the
8
+ * text was baked into the SVG where no prop could reach it, so every install of
9
+ * appkit rendered one Indian marketplace's name in its own header. Both are
10
+ * props now (`wordmark`, `tld`), threaded from `appkit.config.js` through
11
+ * `AppLayoutShell` -> `TitleBarLayout`.
5
12
  *
6
13
  * Single source of truth for the site brand mark. The wordmark gradient
7
14
  * follows the active theme via `var(--appkit-gradient-logo)`, so a custom
8
15
  * admin theme automatically restyles the logo without forking the SVG.
9
16
  *
17
+ * 🛑 The 214-unit viewBox was drawn around an eight-glyph wordmark. A much
18
+ * longer name will overflow it — pass `src` and use a real logo image rather
19
+ * than expecting the SVG to re-letter itself.
20
+ *
10
21
  * Sizes are responsive presets — the variant catalogue forbids consumer-side
11
22
  * className overrides on primitive components.
12
23
  */
@@ -38,18 +49,29 @@ function resolveFill(tone, gradientId) {
38
49
  return `url(#${gradientId})`;
39
50
  }
40
51
  }
41
- export function SiteLogo({ size = "md", tone = "brand", title = "LetItRip.in", src, }) {
52
+ export function SiteLogo({ size = "md", tone = "brand",
53
+ /*
54
+ * 🛑 No brand default. This read `title = "LetItRip.in"`, which put one
55
+ * consumer's name in a library primitive — and the SVG below ignored it
56
+ * anyway, drawing the literal `LetItRip` that no prop could reach.
57
+ *
58
+ * `"Site"` is deliberately bland: an unconfigured install should look
59
+ * obviously unconfigured rather than silently wear someone else's brand.
60
+ */
61
+ title, wordmark, tld, src, }) {
62
+ const text = wordmark ?? title ?? "Site";
63
+ const accessibleTitle = title ?? (tld ? `${text}.${tld}` : text);
42
64
  const uid = useId();
43
65
  const gradientId = `${GRADIENT_ID_PREFIX}-${uid.replace(/:/g, "")}`;
44
66
  const heightCls = SIZE_HEIGHTS[size];
45
67
  if (src) {
46
- return (_jsx(MediaImage, { src: src, alt: title, size: "thumbnail", objectFit: "contain",
68
+ return (_jsx(MediaImage, { src: src, alt: accessibleTitle, size: "thumbnail", objectFit: "contain",
47
69
  // backed by the catalogued `size` enum; no consumer-provided overrides.
48
70
  className: `block w-auto ${heightCls}` }));
49
71
  }
50
72
  const fill = resolveFill(tone, gradientId);
51
73
  const isGradient = tone === "brand";
52
- return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 214 56", role: "img", "aria-label": title, "data-testid": "site-logo",
74
+ return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 214 56", role: "img", "aria-label": accessibleTitle, "data-testid": "site-logo",
53
75
  // backed by the catalogued `size` enum; no consumer-provided overrides.
54
- className: `block w-auto ${heightCls}`, children: [_jsx("title", { children: title }), isGradient && (_jsx("defs", { children: _jsxs("linearGradient", { id: gradientId, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [_jsx("stop", { offset: "0%", style: { stopColor: "var(--appkit-logo-stop-from)" } }), _jsx("stop", { offset: "55%", style: { stopColor: "var(--appkit-logo-stop-mid)" } }), _jsx("stop", { offset: "100%", style: { stopColor: "var(--appkit-logo-stop-to)" } })] }) })), _jsx("text", { x: "0", y: "44", fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif", fontWeight: "800", fontSize: "44", letterSpacing: "-1.5", fill: fill, children: "LetItRip" }), _jsx("rect", { x: "169", y: "5", width: "43", height: "21", rx: "10.5", fill: fill, opacity: "0.12" }), _jsx("text", { x: "174", y: "21", fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif", fontWeight: "700", fontSize: "15", letterSpacing: "0.2", fill: fill, children: ".in" })] }));
76
+ className: `block w-auto ${heightCls}`, children: [_jsx("title", { children: accessibleTitle }), isGradient && (_jsx("defs", { children: _jsxs("linearGradient", { id: gradientId, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [_jsx("stop", { offset: "0%", style: { stopColor: "var(--appkit-logo-stop-from)" } }), _jsx("stop", { offset: "55%", style: { stopColor: "var(--appkit-logo-stop-mid)" } }), _jsx("stop", { offset: "100%", style: { stopColor: "var(--appkit-logo-stop-to)" } })] }) })), _jsx("text", { x: "0", y: "44", fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif", fontWeight: "800", fontSize: "44", letterSpacing: "-1.5", fill: fill, children: text }), tld && (_jsxs(_Fragment, { children: [_jsx("rect", { x: "169", y: "5", width: "43", height: "21", rx: "10.5", fill: fill, opacity: "0.12" }), _jsxs("text", { x: "174", y: "21", fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif", fontWeight: "700", fontSize: "15", letterSpacing: "0.2", fill: fill, children: [".", tld] })] }))] }));
55
77
  }
@@ -11,7 +11,7 @@ export interface SiteMarkProps {
11
11
  * `"on-primary"` renders the mark in `var(--appkit-color-text)`.
12
12
  */
13
13
  tone?: SiteMarkTone;
14
- /** Accessible title; defaults to "LetItRip.in". */
14
+ /** Accessible title. Defaults to the configured brand name. */
15
15
  title?: string;
16
16
  /**
17
17
  * Optional admin-uploaded image URL. When present, renders an `<MediaImage>`
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  /**
4
- * LetItRip site mark — the icon glyph (distinct from the `SiteLogo` text
5
- * wordmark). Sourced from `public/logo.svg`'s path data, recolored to follow
4
+ * Site mark — the icon glyph (distinct from the `SiteLogo` text wordmark).
5
+ * Sourced from `public/logo.svg`'s path data, recolored to follow
6
6
  * the active theme via the same `--appkit-logo-stop-*` variables `SiteLogo`
7
7
  * uses, so a custom admin theme restyles both consistently.
8
8
  *
@@ -10,6 +10,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  * className overrides on primitive components.
11
11
  */
12
12
  import { useId } from "react";
13
+ import { getBrandName } from "../../core/brand-resolver.js";
13
14
  import { MediaImage } from "../../features/media/MediaImage.js";
14
15
  // An SVG <linearGradient> ID prefix, not a class — suffixed with useId()
15
16
  // and referenced as fill="url(#…)".
@@ -62,18 +63,32 @@ const MARK_TRANSFORMS = [
62
63
  "translate(123,146)",
63
64
  "translate(75,187)",
64
65
  ];
65
- export function SiteMark({ size = "md", tone = "brand", title = "LetItRip.in", src, }) {
66
+ export function SiteMark({ size = "md", tone = "brand",
67
+ /*
68
+ * 🛑 Was `title = "LetItRip.in"` — one consumer's name as a library default.
69
+ *
70
+ * Unlike `SiteLogo`, this is NOT the unreachable-glyph bug: the mark is
71
+ * geometric paths with no text, so `title` really is only the accessible
72
+ * name. That makes it the quieter half of the same problem — a screen reader
73
+ * announced this marketplace on every install, and nothing on screen
74
+ * disagreed, so there was no way to notice.
75
+ *
76
+ * Resolved per render rather than at module load, so it reflects
77
+ * `configureBrand()` whenever that ran.
78
+ */
79
+ title, src, }) {
80
+ const accessibleTitle = title ?? getBrandName();
66
81
  const uid = useId();
67
82
  const gradientId = `${GRADIENT_ID_PREFIX}-${uid.replace(/:/g, "")}`;
68
83
  const heightCls = SIZE_HEIGHTS[size];
69
84
  if (src) {
70
- return (_jsx(MediaImage, { src: src, alt: title, size: "thumbnail", objectFit: "contain",
85
+ return (_jsx(MediaImage, { src: src, alt: accessibleTitle, size: "thumbnail", objectFit: "contain",
71
86
  // backed by the catalogued `size` enum; no consumer-provided overrides.
72
87
  className: `block w-auto ${heightCls}` }));
73
88
  }
74
89
  const fill = resolveFill(tone, gradientId);
75
90
  const isGradient = tone === "brand";
76
- return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 236 245", role: "img", "aria-label": title, "data-testid": "site-mark",
91
+ return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 236 245", role: "img", "aria-label": accessibleTitle, "data-testid": "site-mark",
77
92
  // backed by the catalogued `size` enum; no consumer-provided overrides.
78
- className: `block w-auto ${heightCls}`, children: [_jsx("title", { children: title }), isGradient && (_jsx("defs", { children: _jsxs("linearGradient", { id: gradientId, x1: "0%", y1: "0%", x2: "100%", y2: "100%", children: [_jsx("stop", { offset: "0%", style: { stopColor: "var(--appkit-logo-stop-from)" } }), _jsx("stop", { offset: "55%", style: { stopColor: "var(--appkit-logo-stop-mid)" } }), _jsx("stop", { offset: "100%", style: { stopColor: "var(--appkit-logo-stop-to)" } })] }) })), MARK_PATHS.map((d, i) => (_jsx("path", { d: d, fill: fill, transform: MARK_TRANSFORMS[i] }, i)))] }));
93
+ className: `block w-auto ${heightCls}`, children: [_jsx("title", { children: accessibleTitle }), isGradient && (_jsx("defs", { children: _jsxs("linearGradient", { id: gradientId, x1: "0%", y1: "0%", x2: "100%", y2: "100%", children: [_jsx("stop", { offset: "0%", style: { stopColor: "var(--appkit-logo-stop-from)" } }), _jsx("stop", { offset: "55%", style: { stopColor: "var(--appkit-logo-stop-mid)" } }), _jsx("stop", { offset: "100%", style: { stopColor: "var(--appkit-logo-stop-to)" } })] }) })), MARK_PATHS.map((d, i) => (_jsx("path", { d: d, fill: fill, transform: MARK_TRANSFORMS[i] }, i)))] }));
79
94
  }
@@ -7,6 +7,14 @@ export interface TabsProps {
7
7
  children?: React.ReactNode;
8
8
  }
9
9
  export interface TabsListProps {
10
+ /**
11
+ * Never collapse into a dropdown; let the tabs wrap onto a second line.
12
+ *
13
+ * For CONTENT tabs inside a section, where a dropdown reads as a stray form
14
+ * control. Navigation tab bars should leave this `false` — see the note in
15
+ * `TabsList`.
16
+ */
17
+ wrap?: boolean;
10
18
  className?: string;
11
19
  children?: React.ReactNode;
12
20
  }
@@ -30,7 +38,7 @@ export interface TabsContentProps {
30
38
  children?: React.ReactNode;
31
39
  }
32
40
  export declare function Tabs({ defaultValue, value, onChange, className, children, }: TabsProps): React.JSX.Element;
33
- export declare function TabsList({ className, children }: TabsListProps): React.JSX.Element;
41
+ export declare function TabsList({ className, children, wrap }: TabsListProps): React.JSX.Element;
34
42
  export declare function TabsTrigger({ value, disabled, className, children, badge, }: TabsTriggerProps): React.JSX.Element;
35
43
  export declare function TabsContent({ value, className, children, }: TabsContentProps): React.JSX.Element | null;
36
44
  export default Tabs;
@@ -27,7 +27,7 @@ export function Tabs({ defaultValue = "", value, onChange, className = "", child
27
27
  }), [active, onChange, value]);
28
28
  return (_jsx(TabsContext.Provider, { value: contextValue, children: _jsx("div", { className: className, "data-section": "tabs-div-614", children: children }) }));
29
29
  }
30
- export function TabsList({ className = "", children }) {
30
+ export function TabsList({ className = "", children, wrap = false }) {
31
31
  const { active, setActive } = useContext(TabsContext);
32
32
  const shellRef = useRef(null);
33
33
  const rowRef = useRef(null);
@@ -47,7 +47,24 @@ export function TabsList({ className = "", children }) {
47
47
  onSelect: () => setActive(item.props.value),
48
48
  }));
49
49
  const signature = overflowItems.map((i) => `${i.id}:${i.label}:${i.count ?? ""}`).join("|");
50
- const collapsed = useRowCollapse(shellRef, rowRef, signature);
50
+ const measured = useRowCollapse(shellRef, rowRef, signature);
51
+ /*
52
+ * 🛑 `wrap` OPTS OUT OF COLLAPSING ENTIRELY, and it exists because
53
+ * collapsing is only right for NAVIGATION.
54
+ *
55
+ * Owner, 2026-10-27: *"it makes sense for forms or navigations, but no
56
+ * sense for a homepage section's tabs to be coming down."* That is the
57
+ * correct distinction. A nav bar that collapses hides destinations behind
58
+ * one more tap, which is a fair trade on a phone. A content filter inside a
59
+ * section — the homepage FAQ's category tabs — collapses into a dropdown
60
+ * that looks like a form control sitting in the middle of a page, and the
61
+ * visitor cannot see at a glance what the section even contains.
62
+ *
63
+ * Wrapping is the right failure mode here: the tabs take a second line and
64
+ * stay visible. Default stays `false`, so every existing nav tab bar is
65
+ * untouched.
66
+ */
67
+ const collapsed = wrap ? false : measured;
51
68
  /*
52
69
  * Collapsed renders `OverflowRow` in its already-collapsed state rather than
53
70
  * the old `TabsNavSelect`, which was a native `<select>` — so the collapsed
@@ -62,7 +79,7 @@ export function TabsList({ className = "", children }) {
62
79
  if (collapsed) {
63
80
  return (_jsx("div", { ref: shellRef, className: className, children: _jsx(OverflowRow, { items: overflowItems, ariaLabel: "Tabs", activeId: active, alwaysCollapsed: true, searchPlaceholder: "Search tabs\u2026" }) }));
64
81
  }
65
- return (_jsx("div", { ref: shellRef, children: _jsx(TabBarShell, { className: className, ariaLabel: "Tabs", activeKey: active, listRef: rowRef, children: children }) }));
82
+ return (_jsx("div", { ref: shellRef, children: _jsx(TabBarShell, { className: [className, wrap ? "appkit-tabs-list--wrap" : ""].filter(Boolean).join(" "), ariaLabel: "Tabs", activeKey: active, listRef: rowRef, children: children }) }));
66
83
  }
67
84
  export function TabsTrigger({ value, disabled, className = "", children, badge, }) {
68
85
  const { active, setActive } = useContext(TabsContext);
@@ -290,3 +290,23 @@
290
290
  border-color: transparent;
291
291
  color: var(--appkit-tabs-ink-active);
292
292
  }
293
+
294
+ /*
295
+ * Wrapping tab bar — `<TabsList wrap>`.
296
+ *
297
+ * 🛑 For CONTENT tabs inside a page section, never for navigation. The
298
+ * default list scrolls horizontally and collapses into a dropdown once it
299
+ * overflows, which is right for a nav bar on a phone and wrong in the middle
300
+ * of a homepage section: there it renders as a stray form control, and the
301
+ * visitor cannot see what the section contains without opening it.
302
+ *
303
+ * Wrapping keeps every tab visible on a second line. `overflow: visible` is
304
+ * required alongside `flex-wrap` — the base rule's `overflow-x: auto` would
305
+ * otherwise still clip the wrapped rows and reintroduce a scrollbar.
306
+ */
307
+ .appkit-tabs-list--wrap {
308
+ flex-wrap: wrap;
309
+ overflow-x: visible;
310
+ overflow-y: visible;
311
+ scrollbar-width: auto;
312
+ }
@@ -39,16 +39,4 @@ export interface RichTextProps {
39
39
  */
40
40
  charts?: boolean;
41
41
  }
42
- /**
43
- * RichText renders sanitised HTML from a CMS / ProseMirror output.
44
- *
45
- * Security: client-side DOM-based sanitiser strips disallowed tags/attrs.
46
- * For defence-in-depth, also sanitise on the server before storing.
47
- *
48
- * Usage:
49
- * ```tsx
50
- * <RichText html={blogPost.body} className="max-w-2xl" />
51
- * <RichText html={desc} copyableCode />
52
- * ```
53
- */
54
42
  export declare function RichText({ html, className, proseClass, copyableCode, highlightCode, charts, }: RichTextProps): import("react").JSX.Element;
@@ -3,6 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useMemo } from "react";
4
4
  import { Div } from "../components/Div.js";
5
5
  import { normalizeRichTextHtml } from "../../utils/string.formatter.js";
6
+ import { useSiteSettings } from "../../core/hooks/useSiteSettings.js";
6
7
  import { splitChartBlocks } from "./chart-blocks.js";
7
8
  import { ChartFromJson } from "../components/Chart.js";
8
9
  // --- Allowed HTML tags (safe subset — no script/object; iframe allowed for YouTube only) -------
@@ -182,9 +183,59 @@ function attachCopyButtons(container) {
182
183
  * <RichText html={desc} copyableCode />
183
184
  * ```
184
185
  */
186
+ /**
187
+ * Unwrap every `<a>` whose destination the site has closed, keeping its text.
188
+ *
189
+ * 🛑 THIS IS WHERE THE LAST DEAD LINKS WERE, and why six page-level sweeps
190
+ * kept reporting "clean". Stored rich text is authored content that no page
191
+ * template owns: a crawl of the live site on 2026-10-27 found `/scams`,
192
+ * `/tools/authenticity` and `/blog` linked from the HOMEPAGE, and every one
193
+ * of them was inside an FAQ ANSWER. Grepping a page for marketplace words
194
+ * cannot see an href, and gating a section cannot see inside its prose.
195
+ *
196
+ * `RichText` is the single renderer for every stored HTML field on the site —
197
+ * FAQ answers, legal pages, blog bodies, product descriptions — so one filter
198
+ * here covers all of them.
199
+ *
200
+ * 🛑 UNWRAPPED, NOT DELETED. The sentence still reads: "the scam registry is
201
+ * the place to report it" keeps its words and loses its link. Removing the
202
+ * whole anchor would leave a gap mid-sentence, and removing the paragraph
203
+ * would silently delete an admin's copy.
204
+ *
205
+ * Prefix-matched on a `/`-delimited boundary, the same rule as every other
206
+ * gate — `/store` must not match `/stores`.
207
+ */
208
+ function unwrapClosedLinks(html, closed) {
209
+ if (closed.length === 0 || typeof document === "undefined")
210
+ return html;
211
+ const container = document.createElement("div");
212
+ container.innerHTML = html;
213
+ let changed = false;
214
+ for (const a of Array.from(container.querySelectorAll("a[href]"))) {
215
+ const raw = a.getAttribute("href") ?? "";
216
+ if (!raw.startsWith("/"))
217
+ continue;
218
+ const path = raw.split(/[?#]/)[0].replace(/\/+$/, "") || "/";
219
+ // `/en/blog` -> `/blog`: an admin pasting out of the address bar stores
220
+ // the locale-prefixed form, which a raw comparison would miss.
221
+ const bare = path.replace(/^\/[a-z]{2}(?=\/)/, "");
222
+ const hit = closed.some((p) => bare === p || bare.startsWith(`${p}/`) || path === p || path.startsWith(`${p}/`));
223
+ if (!hit)
224
+ continue;
225
+ a.replaceWith(...Array.from(a.childNodes));
226
+ changed = true;
227
+ }
228
+ return changed ? container.innerHTML : html;
229
+ }
185
230
  export function RichText({ html, className = "", proseClass = "prose max-w-none dark:prose-invert", copyableCode = false, highlightCode, charts = true, }) {
231
+ /*
232
+ * Fails OPEN: no settings yet, or a failed fetch, leaves every link intact.
233
+ * A transient error must not strip working links out of an admin's copy.
234
+ */
235
+ const { data: settings } = useSiteSettings();
236
+ const closedPrefixes = settings?.hiddenSurfacePrefixes ?? [];
186
237
  const safe = useMemo(() => {
187
- const sanitized = sanitiseHtml(normalizeRichTextHtml(html));
238
+ const sanitized = unwrapClosedLinks(sanitiseHtml(normalizeRichTextHtml(html)), closedPrefixes);
188
239
  if (!highlightCode || typeof document === "undefined")
189
240
  return sanitized;
190
241
  const container = document.createElement("div");
@@ -20,3 +20,23 @@ export declare function isSameMonth(a: Date | number, b: Date | number): boolean
20
20
  export declare function currentYear(): string;
21
21
  export declare function nowISO(): string;
22
22
  export declare function formatCustomDate(date: Date | string, format?: "short" | "medium" | "long" | "full"): string;
23
+ /**
24
+ * Render a `YYYY-MM` period as "October 2026".
25
+ *
26
+ * Lifted from the consumer's `src/lib/format/inr.ts` (A7), where five
27
+ * ad-booking surfaces shared it.
28
+ *
29
+ * 🛑 `timeZone: "UTC"` is load-bearing and is NOT a default worth overriding.
30
+ * The period is a calendar month with no time in it, so constructing it as UTC
31
+ * midnight and formatting in the viewer's zone renders the PREVIOUS month for
32
+ * anyone west of UTC. India is UTC+5:30, so the bug is invisible to everyone
33
+ * testing it there — which is why the original carried this same note.
34
+ *
35
+ * 🛑 The locale was a hardcoded `"en-IN"` in the consumer copy. It now comes
36
+ * from the market profile, which is the one thing about that helper that was
37
+ * genuinely consumer-specific.
38
+ *
39
+ * Returns the input unchanged when it is not a parseable `YYYY-MM`, rather than
40
+ * rendering "Invalid Date" into a billing table.
41
+ */
42
+ export declare function formatMonthLabel(period: string, locale?: string): string;
@@ -192,3 +192,28 @@ export function formatCustomDate(date, format = "medium") {
192
192
  const options = formatOptions[format] || formatOptions.medium;
193
193
  return dateObj.toLocaleDateString(getDefaultLocale(), options);
194
194
  }
195
+ /**
196
+ * Render a `YYYY-MM` period as "October 2026".
197
+ *
198
+ * Lifted from the consumer's `src/lib/format/inr.ts` (A7), where five
199
+ * ad-booking surfaces shared it.
200
+ *
201
+ * 🛑 `timeZone: "UTC"` is load-bearing and is NOT a default worth overriding.
202
+ * The period is a calendar month with no time in it, so constructing it as UTC
203
+ * midnight and formatting in the viewer's zone renders the PREVIOUS month for
204
+ * anyone west of UTC. India is UTC+5:30, so the bug is invisible to everyone
205
+ * testing it there — which is why the original carried this same note.
206
+ *
207
+ * 🛑 The locale was a hardcoded `"en-IN"` in the consumer copy. It now comes
208
+ * from the market profile, which is the one thing about that helper that was
209
+ * genuinely consumer-specific.
210
+ *
211
+ * Returns the input unchanged when it is not a parseable `YYYY-MM`, rather than
212
+ * rendering "Invalid Date" into a billing table.
213
+ */
214
+ export function formatMonthLabel(period, locale) {
215
+ const [y, m] = period.split("-").map(Number);
216
+ if (!Number.isFinite(y) || !Number.isFinite(m) || m < 1 || m > 12)
217
+ return period;
218
+ return new Date(Date.UTC(y, m - 1, 1)).toLocaleDateString(locale ?? getDefaultLocale(), { month: "long", year: "numeric", timeZone: "UTC" });
219
+ }
@@ -1,6 +1,31 @@
1
1
  /**
2
2
  * Number Formatting Utilities
3
3
  */
4
+ /**
5
+ * Money for PROSE — notification bodies, error messages, log lines, chips.
6
+ *
7
+ * ## Why this exists beside `formatCurrency`
8
+ *
9
+ * 71 call sites interpolated a hardcoded symbol next to a bare number —
10
+ * `` `Minimum offer is ₹${bounds.min}` `` — which is wrong three ways at once:
11
+ * the symbol is baked in, the grouping is absent (`₹1000`, not `₹1,000`), and
12
+ * ~20 more files reached for `toLocaleString("en-IN")` with the locale
13
+ * hardcoded too. All three read from the market profile now, which the consumer
14
+ * already configures via `configureMarketDefaults()`.
15
+ *
16
+ * ## 🛑 Why not just use `formatCurrency`
17
+ *
18
+ * `Intl.NumberFormat` with `style: "currency"` forces the currency's standard
19
+ * fraction digits, so every whole amount becomes `₹1,000.00`. Rewriting 71
20
+ * strings to add `.00` to prices, offers and refunds that are whole amounts is
21
+ * a user-visible copy change dressed up as a refactor. This shows the
22
+ * fractional part only when there is one: `₹1,000` and `₹1,000.50`.
23
+ *
24
+ * `formatCurrency` keeps its job — the ISO-correct, locale-placed rendering for
25
+ * tabular and formal surfaces (invoices, statements). Use that where the form
26
+ * matters and this where the sentence does.
27
+ */
28
+ export declare function formatMoney(amount: number, locale?: string): string;
4
29
  export declare function formatCurrency(amount: number, currency?: string, locale?: string): string;
5
30
  export declare function formatNumber(num: number, locale?: string, options?: {
6
31
  decimals?: number;
@@ -13,3 +38,25 @@ export declare function formatCompactNumber(num: number): string;
13
38
  export declare function formatDecimal(num: number, decimals?: number): string;
14
39
  export declare function formatOrdinal(num: number): string;
15
40
  export declare function parseFormattedNumber(str: string): number;
41
+ /**
42
+ * Whole currency units — no fractional digits — with locale grouping.
43
+ *
44
+ * `₹1,500` for 1499.50. Lifted from the consumer's `src/lib/format/inr.ts`
45
+ * (A5b/A7), where six `/user/*` and ad-booking pages had carried byte-identical
46
+ * private copies before it was consolidated there.
47
+ *
48
+ * ## 🛑 This is NOT `formatMoney`, and must not be collapsed into it
49
+ *
50
+ * `maximumFractionDigits: 0` is the whole point: this ROUNDS, so 1499.50
51
+ * renders `₹1,500`. `formatMoney` keeps the fractional part when there is one.
52
+ * Both are
53
+ * correct for their own surfaces — this one is for figures where the fraction
54
+ * is noise (a monthly ad spend, an order total in a summary row), and the
55
+ * surfaces using it show booking and order totals, so a change in rounding is
56
+ * a change in a number a buyer reads.
57
+ *
58
+ * Converging the two is a product decision about displayed money, not a
59
+ * de-duplication. The consumer's copy carried that warning for exactly this
60
+ * reason and it travels with the function.
61
+ */
62
+ export declare function formatWholeMoney(amount: number, locale?: string): string;
@@ -1,7 +1,57 @@
1
1
  /**
2
2
  * Number Formatting Utilities
3
3
  */
4
- import { getDefaultCurrency, getDefaultLocale, } from "../core/baseline-resolver.js";
4
+ import { getDefaultCurrency, getDefaultCurrencySymbol, getDefaultLocale, } from "../core/baseline-resolver.js";
5
+ /**
6
+ * Money for PROSE — notification bodies, error messages, log lines, chips.
7
+ *
8
+ * ## Why this exists beside `formatCurrency`
9
+ *
10
+ * 71 call sites interpolated a hardcoded symbol next to a bare number —
11
+ * `` `Minimum offer is ₹${bounds.min}` `` — which is wrong three ways at once:
12
+ * the symbol is baked in, the grouping is absent (`₹1000`, not `₹1,000`), and
13
+ * ~20 more files reached for `toLocaleString("en-IN")` with the locale
14
+ * hardcoded too. All three read from the market profile now, which the consumer
15
+ * already configures via `configureMarketDefaults()`.
16
+ *
17
+ * ## 🛑 Why not just use `formatCurrency`
18
+ *
19
+ * `Intl.NumberFormat` with `style: "currency"` forces the currency's standard
20
+ * fraction digits, so every whole amount becomes `₹1,000.00`. Rewriting 71
21
+ * strings to add `.00` to prices, offers and refunds that are whole amounts is
22
+ * a user-visible copy change dressed up as a refactor. This shows the
23
+ * fractional part only when there is one: `₹1,000` and `₹1,000.50`.
24
+ *
25
+ * `formatCurrency` keeps its job — the ISO-correct, locale-placed rendering for
26
+ * tabular and formal surfaces (invoices, statements). Use that where the form
27
+ * matters and this where the sentence does.
28
+ */
29
+ export function formatMoney(amount, locale) {
30
+ const resolvedLocale = locale ?? getDefaultLocale();
31
+ /*
32
+ * 🛑 0 decimals if integral, otherwise exactly 2 — NOT `min: 0, max: 2`.
33
+ *
34
+ * That first draft was wrong and `published-values.ts` caught it: with a
35
+ * floor of 0, `1499.5` renders "₹1,499.5", a money figure with one decimal
36
+ * place. The rule money actually wants is "no trailing .00 on a whole
37
+ * amount, but always both places when there is a fractional part" — exactly
38
+ * what the `formatRupees` this replaced encoded as
39
+ * `minimumFractionDigits: Number.isInteger(amount) ? 0 : 2`, and what its own
40
+ * docstring stated as `₹10`, `₹1,499.50`.
41
+ */
42
+ const fractionDigits = Number.isInteger(amount) ? 0 : 2;
43
+ const grouped = new Intl.NumberFormat(resolvedLocale, {
44
+ minimumFractionDigits: fractionDigits,
45
+ maximumFractionDigits: fractionDigits,
46
+ }).format(amount);
47
+ /*
48
+ * Symbol then number, not `Intl`'s currency placement. These strings are
49
+ * assembled into sentences that already read "₹500" in copy the team wrote,
50
+ * and a locale whose convention is "1 000,00 ₹" would reorder mid-sentence.
51
+ * A market that needs the symbol elsewhere overrides `currencySymbol`.
52
+ */
53
+ return `${getDefaultCurrencySymbol()}${grouped}`;
54
+ }
5
55
  export function formatCurrency(amount, currency, locale) {
6
56
  const resolvedCurrency = currency ?? getDefaultCurrency();
7
57
  const resolvedLocale = locale ?? getDefaultLocale();
@@ -107,3 +157,31 @@ export function parseFormattedNumber(str) {
107
157
  const num = parseFloat(result);
108
158
  return isNegative ? -Math.abs(num) : num;
109
159
  }
160
+ /**
161
+ * Whole currency units — no fractional digits — with locale grouping.
162
+ *
163
+ * `₹1,500` for 1499.50. Lifted from the consumer's `src/lib/format/inr.ts`
164
+ * (A5b/A7), where six `/user/*` and ad-booking pages had carried byte-identical
165
+ * private copies before it was consolidated there.
166
+ *
167
+ * ## 🛑 This is NOT `formatMoney`, and must not be collapsed into it
168
+ *
169
+ * `maximumFractionDigits: 0` is the whole point: this ROUNDS, so 1499.50
170
+ * renders `₹1,500`. `formatMoney` keeps the fractional part when there is one.
171
+ * Both are
172
+ * correct for their own surfaces — this one is for figures where the fraction
173
+ * is noise (a monthly ad spend, an order total in a summary row), and the
174
+ * surfaces using it show booking and order totals, so a change in rounding is
175
+ * a change in a number a buyer reads.
176
+ *
177
+ * Converging the two is a product decision about displayed money, not a
178
+ * de-duplication. The consumer's copy carried that warning for exactly this
179
+ * reason and it travels with the function.
180
+ */
181
+ export function formatWholeMoney(amount, locale) {
182
+ return new Intl.NumberFormat(locale ?? getDefaultLocale(), {
183
+ style: "currency",
184
+ currency: getDefaultCurrency(),
185
+ maximumFractionDigits: 0,
186
+ }).format(amount);
187
+ }
@@ -6,4 +6,3 @@ export declare function normalizePhone(phone: string): string;
6
6
  export declare function formatPhone(phone: string, countryCode?: string): string;
7
7
  export declare function extractCountryCode(phone: string): string | null;
8
8
  export declare function isValidMobile(phone: string, phonePrefix?: string): boolean;
9
- export declare function isValidIndianPincode(pincode: string): boolean;
@@ -36,6 +36,20 @@ export function isValidMobile(phone, phonePrefix) {
36
36
  // Generic: 10-15 digit number
37
37
  return cleaned.length >= 10 && cleaned.length <= 15;
38
38
  }
39
- export function isValidIndianPincode(pincode) {
40
- return /^\d{6}$/.test(pincode.trim());
41
- }
39
+ /*
40
+ * 🛑 `isValidIndianPincode` was REMOVED in A6c. It hardcoded `/^\d{6}$/` — one
41
+ * country's postcode shape in a library meant to be jurisdiction-neutral — and
42
+ * had **zero callers**: the only reference anywhere was its own re-export from
43
+ * `index.ts`, so it was dead code on appkit's public surface.
44
+ *
45
+ * `constants/geo/countries.ts` is the live answer and a better one: 26 countries
46
+ * as DATA (`postalPattern`, `postalLabel`, `hasStates`, `dialCode`) behind
47
+ * `isValidPostalCode` / `postalPatternFor` / `postalLabelFor`, with 17 reader
48
+ * files. Its own header records the bug this function's shape causes —
49
+ * "a Canadian address was being held to `/^\d{6}$/`".
50
+ *
51
+ * That table is also why A6's proposed `IAddressValidationProvider` was not
52
+ * built: the AK2 row describing appkit as doing "pincode-only India validation"
53
+ * predates `countries.ts` and is stale. Postcode rules are a 26-row table, not
54
+ * 26 provider implementations.
55
+ */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohasinac/appkit",
3
- "version": "4.69.1",
3
+ "version": "4.71.0",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -67,7 +67,12 @@
67
67
  "types": "./dist/contracts/registry.d.ts",
68
68
  "import": "./dist/contracts/registry.js"
69
69
  },
70
- "./core/baseline-resolver": {
70
+ "./cli": {
71
+ "types": "./dist/cli/index.d.ts",
72
+ "import": "./dist/cli/index.js",
73
+ "require": "./dist/cli/index.js"
74
+ },
75
+ "./core/baseline-resolver": {
71
76
  "types": "./dist/core/baseline-resolver.d.ts",
72
77
  "import": "./dist/core/baseline-resolver.js"
73
78
  },
@@ -83,7 +88,15 @@
83
88
  "types": "./dist/providers/email-resend/index.d.ts",
84
89
  "import": "./dist/providers/email-resend/index.js"
85
90
  },
86
- "./providers/storage-firebase": {
91
+ "./providers/tax-india-gst": {
92
+ "types": "./dist/providers/tax-india-gst/index.d.ts",
93
+ "import": "./dist/providers/tax-india-gst/index.js"
94
+ },
95
+ "./providers/shipping-shiprocket": {
96
+ "types": "./dist/providers/shipping-shiprocket/index.d.ts",
97
+ "import": "./dist/providers/shipping-shiprocket/index.js"
98
+ },
99
+ "./providers/storage-firebase": {
87
100
  "types": "./dist/providers/storage-firebase/index.d.ts",
88
101
  "import": "./dist/providers/storage-firebase/index.js"
89
102
  },
@@ -317,6 +330,7 @@
317
330
  },
318
331
  "files": [
319
332
  "dist",
333
+ "PROVIDERS.md",
320
334
  "tsconfig.base.json",
321
335
  "scripts/sieve-audit.mjs",
322
336
  "scripts/audit-violations.mjs",
@@ -1,30 +0,0 @@
1
- import React from "react";
2
- import type { AboutHowItem, AboutValueItem, AboutMilestone, AboutTeamMember } from "../schemas/firestore";
3
- export type { AboutHowItem, AboutValueItem, AboutMilestone, AboutTeamMember } from "../schemas/firestore";
4
- export interface AboutViewProps {
5
- labels?: {
6
- title?: string;
7
- subtitle?: string;
8
- missionTitle?: string;
9
- missionText?: string;
10
- howItWorksTitle?: string;
11
- valuesTitle?: string;
12
- valuesSubtitle?: string;
13
- /** When set, renders a link from the values section through to `/ethics`. */
14
- valuesLinkLabel?: string;
15
- milestonesTitle?: string;
16
- teamTitle?: string;
17
- teamSubtitle?: string;
18
- ctaTitle?: string;
19
- ctaSell?: string;
20
- ctaShop?: string;
21
- };
22
- howItems?: AboutHowItem[];
23
- valueItems?: AboutValueItem[];
24
- milestones?: AboutMilestone[];
25
- teamMembers?: AboutTeamMember[];
26
- ctaBannerClass?: string;
27
- /** Render the CTA action buttons */
28
- renderCtaButtons?: () => React.ReactNode;
29
- }
30
- export declare function AboutView({ labels, howItems, valueItems, milestones, teamMembers, ctaBannerClass, renderCtaButtons, }: AboutViewProps): React.JSX.Element;