@mohasinac/appkit 4.62.1 → 4.63.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
  3. package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
  4. package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
  5. package/dist/_internal/server/features/ads/booking.d.ts +118 -0
  6. package/dist/_internal/server/features/ads/booking.js +326 -0
  7. package/dist/_internal/server/features/checkout/actions.d.ts +51 -11
  8. package/dist/_internal/server/features/checkout/actions.js +335 -80
  9. package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
  10. package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
  11. package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
  12. package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
  13. package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
  14. package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
  15. package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
  16. package/dist/_internal/server/features/dashboard/attention.js +183 -0
  17. package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
  18. package/dist/_internal/server/features/dashboard/data.js +82 -0
  19. package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
  20. package/dist/_internal/server/features/inventory/reservations.js +273 -0
  21. package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
  22. package/dist/_internal/server/features/offers/destinations.js +65 -0
  23. package/dist/_internal/server/features/orders/adapters.js +21 -0
  24. package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
  25. package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
  26. package/dist/_internal/server/features/orders/balance.d.ts +89 -0
  27. package/dist/_internal/server/features/orders/balance.js +256 -0
  28. package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
  29. package/dist/_internal/server/features/pricing/actions.js +144 -0
  30. package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
  31. package/dist/_internal/server/features/shipping/book-split.js +130 -0
  32. package/dist/_internal/server/features/shipping/book.d.ts +61 -0
  33. package/dist/_internal/server/features/shipping/book.js +176 -0
  34. package/dist/_internal/server/features/shipping/courier-block.js +26 -1
  35. package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
  36. package/dist/_internal/server/features/site-settings/adapters.js +14 -0
  37. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  38. package/dist/_internal/server/features/stores/adapters.js +14 -0
  39. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  40. package/dist/_internal/server/functions/scheduled.js +57 -1
  41. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +2 -0
  42. package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
  43. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +4 -1
  44. package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
  45. package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
  46. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +15 -0
  47. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  48. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  49. package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
  50. package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
  51. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  52. package/dist/_internal/shared/actions/action-registry.js +268 -0
  53. package/dist/_internal/shared/checkout/order-math.d.ts +31 -2
  54. package/dist/_internal/shared/checkout/order-math.js +22 -36
  55. package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
  56. package/dist/_internal/shared/checkout/rules/index.js +1 -1
  57. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
  58. package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
  59. package/dist/_internal/shared/checkout/split.d.ts +0 -12
  60. package/dist/_internal/shared/checkout/split.js +22 -2
  61. package/dist/_internal/shared/content/disclaimers.js +7 -7
  62. package/dist/_internal/shared/content/published-values.d.ts +6 -1
  63. package/dist/_internal/shared/content/published-values.js +8 -0
  64. package/dist/_internal/shared/features/admin/integrations.d.ts +32 -2
  65. package/dist/_internal/shared/features/admin/integrations.js +19 -9
  66. package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
  67. package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
  68. package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
  69. package/dist/_internal/shared/features/emi/choice.js +69 -0
  70. package/dist/_internal/shared/features/emi/group.d.ts +84 -0
  71. package/dist/_internal/shared/features/emi/group.js +126 -0
  72. package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
  73. package/dist/_internal/shared/features/ledger/posting.js +165 -0
  74. package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
  75. package/dist/_internal/shared/features/ledger/reports.js +127 -0
  76. package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
  77. package/dist/_internal/shared/features/ledger/rules.js +221 -0
  78. package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
  79. package/dist/_internal/shared/features/offers/coordination.js +80 -0
  80. package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
  81. package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
  82. package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
  83. package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
  84. package/dist/_internal/shared/features/points/accepts.d.ts +1 -8
  85. package/dist/_internal/shared/features/points/accepts.js +12 -6
  86. package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
  87. package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
  88. package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
  89. package/dist/_internal/shared/features/shipping/parcel.js +139 -0
  90. package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
  91. package/dist/_internal/shared/features/site-settings/fees.js +12 -8
  92. package/dist/_internal/shared/fees/explain.d.ts +81 -0
  93. package/dist/_internal/shared/fees/explain.js +101 -0
  94. package/dist/_internal/shared/history/index.d.ts +1 -1
  95. package/dist/_internal/shared/history/index.js +1 -1
  96. package/dist/_internal/shared/history/types.d.ts +7 -1
  97. package/dist/_internal/shared/history/types.js +25 -0
  98. package/dist/client.d.ts +11 -1
  99. package/dist/client.js +13 -0
  100. package/dist/constants/api-endpoints.d.ts +72 -0
  101. package/dist/constants/api-endpoints.js +41 -0
  102. package/dist/constants/field-names.d.ts +41 -0
  103. package/dist/constants/field-names.js +47 -0
  104. package/dist/features/account/components/UserOrdersView.js +28 -2
  105. package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
  106. package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
  107. package/dist/features/admin/components/AdminOrderEditorView.d.ts +16 -1
  108. package/dist/features/admin/components/AdminOrderEditorView.js +72 -3
  109. package/dist/features/admin/components/AdminOrdersView.js +20 -1
  110. package/dist/features/admin/schemas/firestore.d.ts +32 -0
  111. package/dist/features/ads/schemas/booking-write.d.ts +157 -0
  112. package/dist/features/ads/schemas/booking-write.js +88 -0
  113. package/dist/features/ads/schemas/creative-form.d.ts +18 -0
  114. package/dist/features/ads/schemas/creative-form.js +51 -0
  115. package/dist/features/ads/schemas/firestore.d.ts +140 -0
  116. package/dist/features/ads/schemas/firestore.js +109 -0
  117. package/dist/features/auctions/repository/bid.repository.js +3 -1
  118. package/dist/features/audit-log/schemas/firestore.d.ts +110 -0
  119. package/dist/features/audit-log/schemas/firestore.js +74 -0
  120. package/dist/features/auth/actions/profile-actions.d.ts +69 -1
  121. package/dist/features/auth/actions/profile-actions.js +62 -1
  122. package/dist/features/auth/schemas/firestore.d.ts +16 -2
  123. package/dist/features/auth/schemas/firestore.js +2 -1
  124. package/dist/features/blog/actions/blog-actions.d.ts +6 -0
  125. package/dist/features/blog/actions/blog-actions.js +17 -2
  126. package/dist/features/blog/api/route.js +4 -1
  127. package/dist/features/blog/columns/index.js +5 -0
  128. package/dist/features/blog/components/BlogIndexPageView.js +2 -1
  129. package/dist/features/blog/repository/blog.repository.d.ts +4 -0
  130. package/dist/features/blog/repository/blog.repository.js +5 -0
  131. package/dist/features/blog/schemas/blog-form.d.ts +3 -0
  132. package/dist/features/blog/schemas/blog-form.js +1 -0
  133. package/dist/features/blog/schemas/firestore.d.ts +38 -1
  134. package/dist/features/blog/schemas/firestore.js +23 -0
  135. package/dist/features/blog/schemas/index.d.ts +6 -0
  136. package/dist/features/blog/schemas/index.js +2 -0
  137. package/dist/features/blog/types/index.d.ts +2 -0
  138. package/dist/features/cart/components/CartPriceBreakdown.d.ts +12 -1
  139. package/dist/features/cart/components/CartPriceBreakdown.js +24 -5
  140. package/dist/features/cart/repository/cart.repository.d.ts +14 -0
  141. package/dist/features/cart/repository/cart.repository.js +20 -0
  142. package/dist/features/cart/schemas/firestore.d.ts +24 -0
  143. package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
  144. package/dist/features/dashboard/components/DashboardHubView.js +56 -0
  145. package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
  146. package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
  147. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
  148. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
  149. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +24 -0
  150. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +28 -0
  151. package/dist/features/dispute-reasons/schemas/firestore.d.ts +3 -5
  152. package/dist/features/events/components/EventSaleBanner.js +1 -1
  153. package/dist/features/faq/components/FAQPageContent.js +2 -2
  154. package/dist/features/gateway-events/schemas/index.d.ts +2 -2
  155. package/dist/features/homepage/schemas/index.d.ts +8 -8
  156. package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
  157. package/dist/features/inventory/schemas/stock-reservation.js +103 -0
  158. package/dist/features/layout/AppLayoutShell.d.ts +9 -1
  159. package/dist/features/layout/AppLayoutShell.js +12 -4
  160. package/dist/features/layout/BottomActions.js +2 -1
  161. package/dist/features/layout/BottomNavbar.d.ts +10 -2
  162. package/dist/features/layout/SideActionDock.js +52 -2
  163. package/dist/features/layout/TitleBarLayout.js +13 -4
  164. package/dist/features/layout/TitleBarLayout.style.css +59 -0
  165. package/dist/features/layout/useCtaReveal.d.ts +16 -1
  166. package/dist/features/layout/useCtaReveal.js +17 -26
  167. package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
  168. package/dist/features/ledger/repository/journal.repository.js +312 -0
  169. package/dist/features/ledger/schemas/expenses.d.ts +87 -0
  170. package/dist/features/ledger/schemas/expenses.js +27 -0
  171. package/dist/features/ledger/schemas/firestore.d.ts +183 -0
  172. package/dist/features/ledger/schemas/firestore.js +69 -0
  173. package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
  174. package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
  175. package/dist/features/orders/components/RaiseDisputeForm.js +19 -11
  176. package/dist/features/orders/repository/orders.repository.d.ts +28 -1
  177. package/dist/features/orders/repository/orders.repository.js +60 -6
  178. package/dist/features/orders/schemas/balance.d.ts +40 -0
  179. package/dist/features/orders/schemas/balance.js +47 -0
  180. package/dist/features/orders/schemas/firestore.d.ts +202 -0
  181. package/dist/features/orders/schemas/firestore.js +43 -0
  182. package/dist/features/orders/schemas/index.d.ts +2 -2
  183. package/dist/features/orders/types/index.d.ts +21 -0
  184. package/dist/features/payments/repository/payout.repository.js +3 -2
  185. package/dist/features/payments/schemas/firestore.d.ts +92 -1
  186. package/dist/features/payments/schemas/firestore.js +23 -0
  187. package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
  188. package/dist/features/pricing/components/AdminPricingView.js +157 -0
  189. package/dist/features/products/schemas/firestore.d.ts +26 -1
  190. package/dist/features/products/schemas/firestore.js +2 -0
  191. package/dist/features/products/schemas/index.d.ts +2 -2
  192. package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
  193. package/dist/features/reviews/repository/reviews.repository.js +16 -0
  194. package/dist/features/scams/repository/scammer.repository.js +2 -1
  195. package/dist/features/scams/schemas/firestore.d.ts +2 -1
  196. package/dist/features/scams/schemas/firestore.js +2 -1
  197. package/dist/features/seller/actions/offer-actions.js +56 -0
  198. package/dist/features/seller/actions/seller-actions.d.ts +1 -1
  199. package/dist/features/seller/actions/seller-actions.js +4 -0
  200. package/dist/features/seller/components/DispatchForm.d.ts +11 -0
  201. package/dist/features/seller/components/DispatchForm.js +190 -0
  202. package/dist/features/seller/components/SellerOrdersView.js +94 -2
  203. package/dist/features/seller/components/index.d.ts +1 -0
  204. package/dist/features/seller/components/index.js +1 -0
  205. package/dist/features/seller/repository/offer.repository.js +4 -3
  206. package/dist/features/seller/schemas/firestore.d.ts +23 -2
  207. package/dist/features/seller/schemas/firestore.js +3 -2
  208. package/dist/features/seller/schemas/index.d.ts +4 -4
  209. package/dist/features/seller/schemas/order-forms.d.ts +61 -4
  210. package/dist/features/seller/schemas/order-forms.js +41 -8
  211. package/dist/features/shipments/schemas/firestore.d.ts +25 -0
  212. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +39 -0
  213. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +55 -0
  214. package/dist/features/shipping-boxes/schemas/firestore.d.ts +2 -4
  215. package/dist/features/stores/repository/store.repository.d.ts +18 -0
  216. package/dist/features/stores/repository/store.repository.js +27 -1
  217. package/dist/features/stores/schemas/firestore.d.ts +41 -0
  218. package/dist/features/stores/schemas/firestore.js +20 -0
  219. package/dist/features/stores/schemas/index.d.ts +6 -6
  220. package/dist/features/support/repository/support.repository.js +72 -6
  221. package/dist/features/support/schemas/firestore.d.ts +17 -0
  222. package/dist/features/support/schemas/index.d.ts +2 -2
  223. package/dist/index.d.ts +5 -0
  224. package/dist/index.js +19 -0
  225. package/dist/next/routing/route-map.d.ts +92 -0
  226. package/dist/next/routing/route-map.js +53 -0
  227. package/dist/react/contexts/SessionContext.d.ts +17 -1
  228. package/dist/schemas/registry.d.ts +22 -16
  229. package/dist/security/pii-schemas.d.ts +1 -1
  230. package/dist/security/pii-schemas.js +45 -0
  231. package/dist/server-entry.d.ts +1 -1
  232. package/dist/server-entry.js +10 -1
  233. package/dist/server.d.ts +29 -1
  234. package/dist/server.js +158 -0
  235. package/dist/styles.css +349 -1
  236. package/dist/tailwind-utilities.css +1 -1
  237. package/dist/ui/components/Button.d.ts +10 -1
  238. package/dist/ui/components/Button.js +25 -3
  239. package/dist/ui/components/Chart.d.ts +63 -0
  240. package/dist/ui/components/Chart.js +169 -0
  241. package/dist/ui/components/Chart.style.css +214 -0
  242. package/dist/ui/components/Disclaimer.js +10 -1
  243. package/dist/ui/components/OverflowRow.js +54 -2
  244. package/dist/ui/components/OverflowRow.style.css +38 -0
  245. package/dist/ui/components/RichTextEditor.js +99 -8
  246. package/dist/ui/components/chart-spec.d.ts +68 -0
  247. package/dist/ui/components/chart-spec.js +140 -0
  248. package/dist/ui/components/index.style.css +1 -0
  249. package/dist/ui/components/surface-tokens.d.ts +1 -1
  250. package/dist/ui/components/surface-tokens.js +9 -0
  251. package/dist/ui/components/toolbar-collapse.d.ts +13 -0
  252. package/dist/ui/components/toolbar-collapse.js +10 -1
  253. package/dist/ui/index.d.ts +6 -0
  254. package/dist/ui/index.js +3 -0
  255. package/dist/ui/rich-text/RichText.d.ts +10 -1
  256. package/dist/ui/rich-text/RichText.js +33 -2
  257. package/dist/ui/rich-text/RichText.style.css +35 -0
  258. package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
  259. package/dist/ui/rich-text/RichTextRenderer.js +34 -2
  260. package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
  261. package/dist/ui/rich-text/chart-blocks.js +87 -0
  262. package/package.json +1 -1
  263. package/scripts/seed-cli.mjs +3 -0
@@ -3,6 +3,14 @@ export interface RichTextRendererProps {
3
3
  html?: string | null;
4
4
  className?: string;
5
5
  proseClass?: string;
6
+ /**
7
+ * Render `<figure data-chart>` placeholders as live charts. Default true.
8
+ *
9
+ * Pass `false` where a chart cannot work — an email body, a plain-text
10
+ * export, an OG image — so the placeholder is simply dropped rather than
11
+ * mounting a client component into a context that cannot hydrate it.
12
+ */
13
+ charts?: boolean;
6
14
  }
7
15
  /**
8
16
  * SSR-safe HTML renderer for admin/CMS-authored rich text content.
@@ -12,5 +20,26 @@ export interface RichTextRendererProps {
12
20
  *
13
21
  * For user-generated content or untrusted HTML, use <RichText> instead
14
22
  * (client-only, runs the DOM-based sanitizer).
23
+ *
24
+ * ## 🛑 It is no longer a single `innerHTML` dump, and why that is safe
25
+ *
26
+ * Chart blocks are stored as `<figure data-chart='{json}'>` and have to become
27
+ * real components to be theme-aware, so the HTML is split and the chart
28
+ * segments are replaced with `<ChartFromJson>`. Two properties keep this from
29
+ * being a regression:
30
+ *
31
+ * - **The fast path is unchanged.** `splitChartBlocks` rejects on a substring
32
+ * test, so content with no chart returns one segment and renders through the
33
+ * same single `dangerouslySetInnerHTML` as before.
34
+ * - **Splitting cannot introduce markup.** Segments are slices of the original
35
+ * string, concatenated in document order; nothing is rewritten. A malformed
36
+ * chart figure fails the match and stays ordinary HTML.
37
+ *
38
+ * 🛑 The prose wrapper stays on the OUTER element, and each segment's own
39
+ * wrapper is `display: contents` (`.appkit-rich-text__seg`). A segment needs an
40
+ * element to carry `dangerouslySetInnerHTML`, but leaving that element in the
41
+ * box tree restarts `prose`'s adjacency and first/last-child margin rules at
42
+ * every chart — so paragraphs either side of a chart would space differently
43
+ * from paragraphs anywhere else on the page.
15
44
  */
16
- export declare function RichTextRenderer({ html, className, proseClass, }: RichTextRendererProps): React.JSX.Element | null;
45
+ export declare function RichTextRenderer({ html, className, proseClass, charts, }: RichTextRendererProps): React.JSX.Element | null;
@@ -1,4 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { splitChartBlocks } from "./chart-blocks.js";
3
+ import { ChartFromJson } from "../components/Chart.js";
2
4
  /**
3
5
  * SSR-safe HTML renderer for admin/CMS-authored rich text content.
4
6
  *
@@ -7,9 +9,39 @@ import { jsx as _jsx } from "react/jsx-runtime";
7
9
  *
8
10
  * For user-generated content or untrusted HTML, use <RichText> instead
9
11
  * (client-only, runs the DOM-based sanitizer).
12
+ *
13
+ * ## 🛑 It is no longer a single `innerHTML` dump, and why that is safe
14
+ *
15
+ * Chart blocks are stored as `<figure data-chart='{json}'>` and have to become
16
+ * real components to be theme-aware, so the HTML is split and the chart
17
+ * segments are replaced with `<ChartFromJson>`. Two properties keep this from
18
+ * being a regression:
19
+ *
20
+ * - **The fast path is unchanged.** `splitChartBlocks` rejects on a substring
21
+ * test, so content with no chart returns one segment and renders through the
22
+ * same single `dangerouslySetInnerHTML` as before.
23
+ * - **Splitting cannot introduce markup.** Segments are slices of the original
24
+ * string, concatenated in document order; nothing is rewritten. A malformed
25
+ * chart figure fails the match and stays ordinary HTML.
26
+ *
27
+ * 🛑 The prose wrapper stays on the OUTER element, and each segment's own
28
+ * wrapper is `display: contents` (`.appkit-rich-text__seg`). A segment needs an
29
+ * element to carry `dangerouslySetInnerHTML`, but leaving that element in the
30
+ * box tree restarts `prose`'s adjacency and first/last-child margin rules at
31
+ * every chart — so paragraphs either side of a chart would space differently
32
+ * from paragraphs anywhere else on the page.
10
33
  */
11
- export function RichTextRenderer({ html, className = "", proseClass = "prose max-w-none dark:prose-invert", }) {
34
+ export function RichTextRenderer({ html, className = "", proseClass = "prose max-w-none dark:prose-invert", charts = true, }) {
12
35
  if (!html)
13
36
  return null;
14
- return (_jsx("div", { className: `appkit-rich-text ${proseClass} ${className}`.trim(), dangerouslySetInnerHTML: { __html: html } }));
37
+ const wrapperClass = `appkit-rich-text ${proseClass} ${className}`.trim();
38
+ const segments = charts ? splitChartBlocks(html) : [{ type: "html", html }];
39
+ // Single HTML segment — the overwhelmingly common case. Identical to the
40
+ // pre-chart behaviour, down to the element shape.
41
+ if (segments.length === 1 && segments[0].type === "html") {
42
+ return (_jsx("div", { className: wrapperClass, dangerouslySetInnerHTML: { __html: segments[0].html } }));
43
+ }
44
+ return (_jsx("div", { className: wrapperClass, children: segments.map((seg, i) => seg.type === "html" ? (_jsx("div", { className: "appkit-rich-text__seg", dangerouslySetInnerHTML: { __html: seg.html } }, `h${i}`)) : (
45
+ // eslint-disable-next-line react/no-array-index-key
46
+ _jsx(ChartFromJson, { json: seg.json }, `c${i}`))) }));
15
47
  }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Splitting rich-text HTML around `<figure data-chart>` placeholders.
3
+ *
4
+ * ## 🛑 Why this is regex and not a DOM parse
5
+ *
6
+ * `RichTextRenderer` is a React Server Component — no `DOMParser`, no
7
+ * `document`. So the split has to work on the string, and it is only safe to do
8
+ * that because the shape being matched is one we WRITE: a childless
9
+ * `<figure data-chart='…'></figure>` emitted by the chart toolbar button.
10
+ *
11
+ * This is deliberately not a general HTML parser and must not grow into one. It
12
+ * matches exactly one element shape and hands everything else through
13
+ * untouched, so a malformed chart figure degrades to "rendered as ordinary
14
+ * HTML" rather than corrupting the document around it.
15
+ *
16
+ * ## 🛑 Why the JSON needs entity decoding
17
+ *
18
+ * A `ChartSpec` is full of `"` characters, so the attribute is written
19
+ * single-quoted. But anything that round-trips the HTML through a DOM — the
20
+ * client sanitiser's `DOMParser`, a contenteditable surface, an admin preview —
21
+ * re-serialises it double-quoted with the inner quotes as `&quot;`. Both
22
+ * spellings therefore occur in stored content, and a renderer that handles only
23
+ * the one it writes will fail on its own saved output.
24
+ *
25
+ * Pure. No React, no DOM, safe on the server.
26
+ */
27
+ import type { ChartSpec } from "../components/chart-spec";
28
+ /** A run of ordinary HTML, or a chart placeholder's raw JSON payload. */
29
+ export type RichTextSegment = {
30
+ type: "html";
31
+ html: string;
32
+ } | {
33
+ type: "chart";
34
+ json: string;
35
+ };
36
+ /**
37
+ * Decode the entity subset an HTML serialiser can introduce inside an
38
+ * attribute value.
39
+ *
40
+ * 🛑 `&amp;` is decoded LAST. Decoding it first turns a legitimately encoded
41
+ * `&amp;quot;` into `&quot;` and then into `"`, which injects a quote the
42
+ * author never wrote and breaks the JSON parse — the classic double-decode bug.
43
+ */
44
+ export declare function decodeAttrEntities(s: string): string;
45
+ /**
46
+ * Split HTML into alternating prose and chart segments, in document order.
47
+ *
48
+ * Returns a single `html` segment when there are no charts, so the common case
49
+ * costs one regex test and the caller's fast path stays a plain innerHTML
50
+ * render.
51
+ */
52
+ export declare function splitChartBlocks(html: string): RichTextSegment[];
53
+ /** True when the content carries at least one chart placeholder. Stateless. */
54
+ export declare function hasChartBlock(html: string | null | undefined): boolean;
55
+ /**
56
+ * Build the placeholder a toolbar or a seed fixture should emit.
57
+ *
58
+ * Single-quoted, with any single quote in the payload escaped as `&#39;` so the
59
+ * attribute cannot be terminated early by a label containing an apostrophe —
60
+ * "Blader's choice" is an entirely ordinary series label.
61
+ */
62
+ export declare function chartFigureHtml(spec: ChartSpec): string;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Matches a childless `<figure>` carrying `data-chart`, single- or
3
+ * double-quoted. `[\s\S]*?` rather than `.*?` because stored content is
4
+ * frequently pretty-printed across lines.
5
+ */
6
+ const CHART_FIGURE_RE = /<figure\b[^>]*\bdata-chart\s*=\s*(?:'([^']*)'|"([^"]*)")[^>]*>[\s\S]*?<\/figure\s*>/gi;
7
+ /**
8
+ * 🛑 A SECOND, non-global copy, purely for `hasChartBlock`.
9
+ *
10
+ * `RegExp.prototype.test` on a `/g` regex ADVANCES `lastIndex`, so calling it
11
+ * twice on the same string returns `true` then `false`. Measured on the first
12
+ * draft of this file: three consecutive calls gave `true false true`. Sharing
13
+ * one `/g` literal between `exec` in a loop and `test` as a predicate is the
14
+ * bug — a predicate must be stateless, so it gets its own non-global regex
15
+ * rather than relying on every caller to reset `lastIndex` first.
16
+ *
17
+ * Derived from `.source` so the pattern has exactly one definition. It is also
18
+ * written as a LITERAL above rather than built from a string: a string-built
19
+ * pattern needs every backslash doubled, which is silently destroyed by any
20
+ * tool that re-escapes the file on the way in — a draft of this module lost
21
+ * `\s` to `s` that way and matched nothing at all while looking correct.
22
+ */
23
+ const CHART_FIGURE_TEST_RE = new RegExp(CHART_FIGURE_RE.source, "i");
24
+ /**
25
+ * Decode the entity subset an HTML serialiser can introduce inside an
26
+ * attribute value.
27
+ *
28
+ * 🛑 `&amp;` is decoded LAST. Decoding it first turns a legitimately encoded
29
+ * `&amp;quot;` into `&quot;` and then into `"`, which injects a quote the
30
+ * author never wrote and breaks the JSON parse — the classic double-decode bug.
31
+ */
32
+ export function decodeAttrEntities(s) {
33
+ return s
34
+ .replace(/&quot;/g, '"')
35
+ .replace(/&#0*39;/g, "'")
36
+ .replace(/&apos;/g, "'")
37
+ .replace(/&lt;/g, "<")
38
+ .replace(/&gt;/g, ">")
39
+ .replace(/&amp;/g, "&");
40
+ }
41
+ /**
42
+ * Split HTML into alternating prose and chart segments, in document order.
43
+ *
44
+ * Returns a single `html` segment when there are no charts, so the common case
45
+ * costs one regex test and the caller's fast path stays a plain innerHTML
46
+ * render.
47
+ */
48
+ export function splitChartBlocks(html) {
49
+ if (!html)
50
+ return [];
51
+ // Cheap reject before the real scan — most content has no chart at all.
52
+ if (!html.includes("data-chart"))
53
+ return [{ type: "html", html }];
54
+ const segments = [];
55
+ let cursor = 0;
56
+ // `exec` in a loop needs a fresh lastIndex; the literal is module-scoped and
57
+ // /g, so reset rather than relying on a previous call having run to the end.
58
+ CHART_FIGURE_RE.lastIndex = 0;
59
+ let m;
60
+ while ((m = CHART_FIGURE_RE.exec(html)) !== null) {
61
+ if (m.index > cursor) {
62
+ segments.push({ type: "html", html: html.slice(cursor, m.index) });
63
+ }
64
+ const raw = m[1] ?? m[2] ?? "";
65
+ segments.push({ type: "chart", json: decodeAttrEntities(raw) });
66
+ cursor = m.index + m[0].length;
67
+ }
68
+ if (cursor < html.length) {
69
+ segments.push({ type: "html", html: html.slice(cursor) });
70
+ }
71
+ return segments;
72
+ }
73
+ /** True when the content carries at least one chart placeholder. Stateless. */
74
+ export function hasChartBlock(html) {
75
+ return !!html && CHART_FIGURE_TEST_RE.test(html);
76
+ }
77
+ /**
78
+ * Build the placeholder a toolbar or a seed fixture should emit.
79
+ *
80
+ * Single-quoted, with any single quote in the payload escaped as `&#39;` so the
81
+ * attribute cannot be terminated early by a label containing an apostrophe —
82
+ * "Blader's choice" is an entirely ordinary series label.
83
+ */
84
+ export function chartFigureHtml(spec) {
85
+ const json = JSON.stringify(spec).replace(/'/g, "&#39;");
86
+ return `<figure data-chart='${json}'></figure>`;
87
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohasinac/appkit",
3
- "version": "4.62.1",
3
+ "version": "4.63.1",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -274,6 +274,7 @@ const {
274
274
  wishlistsSeedData, historySeedData,
275
275
  groupedListingsSeedData,
276
276
  mediaAssetsSeedData, mediaAssetsEditorialSeedData,
277
+ chartOfAccountsSeedData,
277
278
  scammersSeedData, productFeaturesSeedData, taxCodesSeedData,
278
279
  disputeReasonsSeedData,
279
280
  authenticityKnowledgeSeedData,
@@ -387,6 +388,7 @@ const COLLECTION_MAP = {
387
388
  * precisely so a Firestore wipe cannot orphan Storage.
388
389
  */
389
390
  mediaAssets: "mediaAssets",
391
+ chartOfAccounts: "chartOfAccounts",
390
392
  scammerProfiles: SCAMMER_COLLECTION,
391
393
  productFeatures: PRODUCT_FEATURES_COLLECTION,
392
394
  authenticityKnowledge: "authenticityKnowledge",
@@ -769,6 +771,7 @@ const SEED_DATA_MAP = {
769
771
  // rewritten wholesale by upload-taxonomy-images.mjs, so the editorial rows
770
772
  // are kept beside them rather than inside that file.
771
773
  mediaAssets: [...mediaAssetsSeedData, ...mediaAssetsEditorialSeedData],
774
+ chartOfAccounts: chartOfAccountsSeedData,
772
775
  scammerProfiles: scammersSeedData,
773
776
  productFeatures: productFeaturesSeedData,
774
777
  authenticityKnowledge: authenticityKnowledgeSeedData,