@openrails/billing-ui 0.241.0 → 0.243.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 (265) hide show
  1. package/CHANGELOG.md +27 -11
  2. package/README.md +41 -8
  3. package/dist/admin/billing-admin.d.ts +3 -0
  4. package/dist/admin/components/app-sidebar.d.ts +1 -0
  5. package/dist/admin/components/confirm.d.ts +4 -0
  6. package/dist/admin/components/cursor-pager.d.ts +8 -0
  7. package/dist/admin/components/data-table.d.ts +14 -0
  8. package/dist/admin/components/fact-card.d.ts +5 -0
  9. package/dist/admin/components/form-field-errors.d.ts +3 -0
  10. package/dist/admin/components/linked-table-row.d.ts +5 -0
  11. package/dist/admin/components/logo.d.ts +3 -0
  12. package/dist/admin/components/no-access.d.ts +3 -0
  13. package/dist/admin/components/no-merchants.d.ts +1 -0
  14. package/dist/admin/components/notification-bell.d.ts +2 -0
  15. package/dist/admin/components/route-error.d.ts +3 -0
  16. package/dist/admin/components/site-header.d.ts +9 -0
  17. package/dist/admin/components/status-badge.d.ts +3 -0
  18. package/dist/admin/components/typed-confirm-dialog.d.ts +11 -0
  19. package/dist/admin/components/ui/alert-dialog.d.ts +18 -0
  20. package/dist/admin/components/ui/avatar.d.ts +11 -0
  21. package/dist/admin/components/ui/badge.d.ts +7 -0
  22. package/dist/admin/components/ui/breadcrumb.d.ts +10 -0
  23. package/dist/admin/components/ui/button.d.ts +8 -0
  24. package/dist/admin/components/ui/card.d.ts +11 -0
  25. package/dist/admin/components/ui/chart.d.ts +44 -0
  26. package/dist/admin/components/ui/dialog.d.ts +17 -0
  27. package/dist/admin/components/ui/dropdown-menu.d.ts +29 -0
  28. package/dist/admin/components/ui/input.d.ts +3 -0
  29. package/dist/admin/components/ui/label.d.ts +3 -0
  30. package/dist/admin/components/ui/select.d.ts +15 -0
  31. package/dist/admin/components/ui/separator.d.ts +3 -0
  32. package/dist/admin/components/ui/sheet.d.ts +14 -0
  33. package/dist/admin/components/ui/sidebar.d.ts +63 -0
  34. package/dist/admin/components/ui/skeleton.d.ts +2 -0
  35. package/dist/admin/components/ui/sonner.d.ts +3 -0
  36. package/dist/admin/components/ui/switch.d.ts +5 -0
  37. package/dist/admin/components/ui/table.d.ts +10 -0
  38. package/dist/admin/components/ui/tabs.d.ts +10 -0
  39. package/dist/admin/components/ui/textarea.d.ts +3 -0
  40. package/dist/admin/components/ui/tooltip.d.ts +6 -0
  41. package/dist/admin/context.d.ts +1193 -0
  42. package/dist/admin/hooks/use-mobile.d.ts +1 -0
  43. package/dist/admin/index.d.ts +5 -0
  44. package/dist/admin/layouts/app-layout.d.ts +4 -0
  45. package/dist/admin/lib/api/client.d.ts +64 -0
  46. package/dist/admin/lib/api/copilot.d.ts +6 -0
  47. package/dist/admin/lib/api/credit-endpoints.d.ts +8 -0
  48. package/dist/admin/lib/api/credit-types.d.ts +9 -0
  49. package/dist/admin/lib/api/endpoints.d.ts +133 -0
  50. package/dist/admin/lib/api/index.d.ts +89 -0
  51. package/dist/admin/lib/api/invoice-profile-endpoints.d.ts +6 -0
  52. package/dist/admin/lib/api/metrics.d.ts +68 -0
  53. package/dist/admin/lib/api/order-endpoints.d.ts +21 -0
  54. package/dist/admin/lib/api/types.d.ts +122 -0
  55. package/dist/admin/lib/auth.d.ts +6 -0
  56. package/dist/admin/lib/capabilities.d.ts +13 -0
  57. package/dist/admin/lib/chunk-error.d.ts +1 -0
  58. package/dist/admin/lib/confirm.d.ts +11 -0
  59. package/dist/admin/lib/credit-queries.d.ts +23 -0
  60. package/dist/admin/lib/csv.d.ts +3 -0
  61. package/dist/admin/lib/cursor-pages.d.ts +13 -0
  62. package/dist/admin/lib/dialog-width.d.ts +6 -0
  63. package/dist/admin/lib/dom.d.ts +1 -0
  64. package/dist/admin/lib/duration.d.ts +3 -0
  65. package/dist/admin/lib/format.d.ts +23 -0
  66. package/dist/admin/lib/mount.d.ts +6 -0
  67. package/dist/admin/lib/mutations.d.ts +125 -0
  68. package/dist/admin/lib/order-queries.d.ts +29 -0
  69. package/dist/admin/lib/queries.d.ts +369 -0
  70. package/dist/admin/lib/query-client.d.ts +3 -0
  71. package/dist/admin/lib/toast.d.ts +10 -0
  72. package/dist/admin/lib/utils.d.ts +2 -0
  73. package/dist/admin/messages.d.ts +670 -0
  74. package/dist/admin/navigation.d.ts +14 -0
  75. package/dist/admin/pages/catalog/application-dialog.d.ts +2 -0
  76. package/dist/admin/pages/catalog/copilot-panel.d.ts +4 -0
  77. package/dist/admin/pages/catalog/index.d.ts +4 -0
  78. package/dist/admin/pages/catalog/meter-form.d.ts +6 -0
  79. package/dist/admin/pages/catalog/metering-model.d.ts +67 -0
  80. package/dist/admin/pages/catalog/metering.d.ts +3 -0
  81. package/dist/admin/pages/catalog/price-detail.d.ts +2 -0
  82. package/dist/admin/pages/catalog/price-format.d.ts +3 -0
  83. package/dist/admin/pages/catalog/price-wizard-logic.d.ts +20 -0
  84. package/dist/admin/pages/catalog/price-wizard.d.ts +10 -0
  85. package/dist/admin/pages/catalog/psp-links.d.ts +10 -0
  86. package/dist/admin/pages/catalog/rate-card-editor.d.ts +10 -0
  87. package/dist/admin/pages/customers/credit-form.d.ts +14 -0
  88. package/dist/admin/pages/customers/credits.d.ts +5 -0
  89. package/dist/admin/pages/customers/default-card-badges.d.ts +3 -0
  90. package/dist/admin/pages/customers/detail.d.ts +5 -0
  91. package/dist/admin/pages/customers/grant-duration.d.ts +32 -0
  92. package/dist/admin/pages/customers/index.d.ts +2 -0
  93. package/dist/admin/pages/customers/invoice-profile-model.d.ts +18 -0
  94. package/dist/admin/pages/customers/invoice-profile.d.ts +9 -0
  95. package/dist/admin/pages/dashboard/index.d.ts +2 -0
  96. package/dist/admin/pages/dashboard/lib.d.ts +48 -0
  97. package/dist/admin/pages/dashboard/range-picker.d.ts +1 -0
  98. package/dist/admin/pages/dashboard/range.d.ts +34 -0
  99. package/dist/admin/pages/dashboard/reports-model.d.ts +29 -0
  100. package/dist/admin/pages/dashboard/reports.d.ts +2 -0
  101. package/dist/admin/pages/dashboard/use-range.d.ts +5 -0
  102. package/dist/admin/pages/dashboard/widget-editor.d.ts +8 -0
  103. package/dist/admin/pages/dashboard/widget-tile.d.ts +9 -0
  104. package/dist/admin/pages/dashboard/widget-viz.d.ts +12 -0
  105. package/dist/admin/pages/ops/index.d.ts +2 -0
  106. package/dist/admin/pages/orders/detail.d.ts +5 -0
  107. package/dist/admin/pages/orders/index.d.ts +1 -0
  108. package/dist/admin/pages/orders/model.d.ts +7 -0
  109. package/dist/admin/pages/payments/attempts.d.ts +7 -0
  110. package/dist/admin/pages/payments/detail.d.ts +2 -0
  111. package/dist/admin/pages/payments/health-model.d.ts +149 -0
  112. package/dist/admin/pages/payments/health.d.ts +2 -0
  113. package/dist/admin/pages/payments/index.d.ts +2 -0
  114. package/dist/admin/pages/settings/configuration-edit.d.ts +9 -0
  115. package/dist/admin/pages/settings/index.d.ts +9 -0
  116. package/dist/admin/pages/settings/notifications.d.ts +2 -0
  117. package/dist/admin/pages/settings/setting-fields.d.ts +20 -0
  118. package/dist/admin/pages/subscriptions/change-subscription-dialog.d.ts +16 -0
  119. package/dist/admin/pages/subscriptions/detail.d.ts +2 -0
  120. package/dist/admin/pages/subscriptions/dunning.d.ts +2 -0
  121. package/dist/admin/pages/subscriptions/index.d.ts +2 -0
  122. package/dist/admin/pages/subscriptions/subscription-change-options.d.ts +23 -0
  123. package/dist/admin/pages/subscriptions/views.d.ts +15 -0
  124. package/dist/admin/router.d.ts +32 -0
  125. package/dist/admin/routes.d.ts +5 -0
  126. package/dist/admin/summary.d.ts +27 -0
  127. package/dist/admin/theme.d.ts +2 -0
  128. package/dist/admin/types.d.ts +56 -0
  129. package/dist/admin/ui-context.d.ts +14 -0
  130. package/dist/admin-attempts-lAoW-Urd.js +419 -0
  131. package/dist/admin-attempts-lAoW-Urd.js.map +1 -0
  132. package/dist/admin-auth-DQGHtt0j.js +14 -0
  133. package/dist/admin-auth-DQGHtt0j.js.map +1 -0
  134. package/dist/admin-badge-DR5-1qd8.js +31 -0
  135. package/dist/admin-badge-DR5-1qd8.js.map +1 -0
  136. package/dist/admin-button-CTL3DgOt.js +46 -0
  137. package/dist/admin-button-CTL3DgOt.js.map +1 -0
  138. package/dist/admin-capabilities-BuigAgtm.js +59 -0
  139. package/dist/admin-capabilities-BuigAgtm.js.map +1 -0
  140. package/dist/admin-card-bzAks3-3.js +51 -0
  141. package/dist/admin-card-bzAks3-3.js.map +1 -0
  142. package/dist/admin-catalog-CC7I4n0_.js +1189 -0
  143. package/dist/admin-catalog-CC7I4n0_.js.map +1 -0
  144. package/dist/admin-confirm-katGq0Qo.js +12 -0
  145. package/dist/admin-confirm-katGq0Qo.js.map +1 -0
  146. package/dist/admin-csv-CPoNZj2D.js +16 -0
  147. package/dist/admin-csv-CPoNZj2D.js.map +1 -0
  148. package/dist/admin-customers-D8u5gq3M.js +160 -0
  149. package/dist/admin-customers-D8u5gq3M.js.map +1 -0
  150. package/dist/admin-dashboard-DqqFjOzq.js +420 -0
  151. package/dist/admin-dashboard-DqqFjOzq.js.map +1 -0
  152. package/dist/admin-data-table-qfXLOFmN.js +96 -0
  153. package/dist/admin-data-table-qfXLOFmN.js.map +1 -0
  154. package/dist/admin-detail-5aNNvrc0.js +324 -0
  155. package/dist/admin-detail-5aNNvrc0.js.map +1 -0
  156. package/dist/admin-detail-7p684Uyc.js +342 -0
  157. package/dist/admin-detail-7p684Uyc.js.map +1 -0
  158. package/dist/admin-detail-CGOyqs7s.js +1312 -0
  159. package/dist/admin-detail-CGOyqs7s.js.map +1 -0
  160. package/dist/admin-detail-DUAJQg8G.js +710 -0
  161. package/dist/admin-detail-DUAJQg8G.js.map +1 -0
  162. package/dist/admin-dialog-BjuKI5Hp.js +88 -0
  163. package/dist/admin-dialog-BjuKI5Hp.js.map +1 -0
  164. package/dist/admin-dialog-width-BPrgdYlj.js +6 -0
  165. package/dist/admin-dialog-width-BPrgdYlj.js.map +1 -0
  166. package/dist/admin-dom-uMmZzRvU.js +149 -0
  167. package/dist/admin-dom-uMmZzRvU.js.map +1 -0
  168. package/dist/admin-dropdown-menu-BW1D_h6s.js +69 -0
  169. package/dist/admin-dropdown-menu-BW1D_h6s.js.map +1 -0
  170. package/dist/admin-dunning-B2zgtrOo.js +10 -0
  171. package/dist/admin-dunning-B2zgtrOo.js.map +1 -0
  172. package/dist/admin-fact-card-DO_fHosg.js +20 -0
  173. package/dist/admin-fact-card-DO_fHosg.js.map +1 -0
  174. package/dist/admin-form-field-errors-hbUMIriS.js +14 -0
  175. package/dist/admin-form-field-errors-hbUMIriS.js.map +1 -0
  176. package/dist/admin-format-DoohJ7Fg.js +136 -0
  177. package/dist/admin-format-DoohJ7Fg.js.map +1 -0
  178. package/dist/admin-health-B4jN2LwR.js +983 -0
  179. package/dist/admin-health-B4jN2LwR.js.map +1 -0
  180. package/dist/admin-input-CcfQfJFN.js +17 -0
  181. package/dist/admin-input-CcfQfJFN.js.map +1 -0
  182. package/dist/admin-invoice-profile-model-Cgjy3zV8.js +53 -0
  183. package/dist/admin-invoice-profile-model-Cgjy3zV8.js.map +1 -0
  184. package/dist/admin-label-BiEN5cjb.js +15 -0
  185. package/dist/admin-label-BiEN5cjb.js.map +1 -0
  186. package/dist/admin-linked-table-row-BsaUruCN.js +26 -0
  187. package/dist/admin-linked-table-row-BsaUruCN.js.map +1 -0
  188. package/dist/admin-metering-BGAXbT23.js +1702 -0
  189. package/dist/admin-metering-BGAXbT23.js.map +1 -0
  190. package/dist/admin-ops-B3mcr76u.js +217 -0
  191. package/dist/admin-ops-B3mcr76u.js.map +1 -0
  192. package/dist/admin-orders-dxC99Idl.js +192 -0
  193. package/dist/admin-orders-dxC99Idl.js.map +1 -0
  194. package/dist/admin-payments-Bs7HSfP0.js +246 -0
  195. package/dist/admin-payments-Bs7HSfP0.js.map +1 -0
  196. package/dist/admin-price-detail-DRquxpA9.js +482 -0
  197. package/dist/admin-price-detail-DRquxpA9.js.map +1 -0
  198. package/dist/admin-price-format-DM1qORWI.js +44 -0
  199. package/dist/admin-price-format-DM1qORWI.js.map +1 -0
  200. package/dist/admin-price-wizard-CI7K-2Nz.js +357 -0
  201. package/dist/admin-price-wizard-CI7K-2Nz.js.map +1 -0
  202. package/dist/admin-range-picker-Dr2M1EZr.js +192 -0
  203. package/dist/admin-range-picker-Dr2M1EZr.js.map +1 -0
  204. package/dist/admin-reports-CywKLiSA.js +320 -0
  205. package/dist/admin-reports-CywKLiSA.js.map +1 -0
  206. package/dist/admin-select-DBgprVW6.js +81 -0
  207. package/dist/admin-select-DBgprVW6.js.map +1 -0
  208. package/dist/admin-settings-Bmoy95uO.js +1434 -0
  209. package/dist/admin-settings-Bmoy95uO.js.map +1 -0
  210. package/dist/admin-skeleton-DsM7crYi.js +14 -0
  211. package/dist/admin-skeleton-DsM7crYi.js.map +1 -0
  212. package/dist/admin-status-badge-BFPgo71d.js +38 -0
  213. package/dist/admin-status-badge-BFPgo71d.js.map +1 -0
  214. package/dist/admin-subscriptions-CLYc_HEV.js +301 -0
  215. package/dist/admin-subscriptions-CLYc_HEV.js.map +1 -0
  216. package/dist/admin-switch-BJUxLCsa.js +20 -0
  217. package/dist/admin-switch-BJUxLCsa.js.map +1 -0
  218. package/dist/admin-table-CH9TrXJf.js +61 -0
  219. package/dist/admin-table-CH9TrXJf.js.map +1 -0
  220. package/dist/admin-tabs-528FJMjt.js +46 -0
  221. package/dist/admin-tabs-528FJMjt.js.map +1 -0
  222. package/dist/admin-textarea-DEz38RaI.js +15 -0
  223. package/dist/admin-textarea-DEz38RaI.js.map +1 -0
  224. package/dist/admin-typed-confirm-dialog-DU7m9-O7.js +66 -0
  225. package/dist/admin-typed-confirm-dialog-DU7m9-O7.js.map +1 -0
  226. package/dist/admin-utils-BK4Vh1o_.js +1809 -0
  227. package/dist/admin-utils-BK4Vh1o_.js.map +1 -0
  228. package/dist/admin-widget-viz-Da48c-Zf.js +581 -0
  229. package/dist/admin-widget-viz-Da48c-Zf.js.map +1 -0
  230. package/dist/admin.css +3 -0
  231. package/dist/admin.js +2164 -0
  232. package/dist/admin.js.map +1 -0
  233. package/dist/appearance.d.ts +1 -1
  234. package/dist/client/generated/error-codes.d.ts +1 -1
  235. package/dist/client/generated/routes.d.ts +2156 -189
  236. package/dist/client/generated/wire.d.ts +1265 -50
  237. package/dist/client/types.d.ts +0 -1
  238. package/dist/{client-Cxz_miQj.js → client-PjivPHmE.js} +2 -3
  239. package/dist/client-PjivPHmE.js.map +1 -0
  240. package/dist/client.js +1 -1
  241. package/dist/{hooks-aKefXeMO.js → hooks-Ckd8F2JF.js} +8 -8
  242. package/dist/hooks-Ckd8F2JF.js.map +1 -0
  243. package/dist/index.d.ts +1 -1
  244. package/dist/index.js +12 -12
  245. package/dist/index.js.map +1 -1
  246. package/dist/lib/{offer-label.d.ts → price-label.d.ts} +1 -1
  247. package/dist/locales/de.js +1 -1
  248. package/dist/locales/de.js.map +1 -1
  249. package/dist/locales/en.d.ts +1 -1
  250. package/dist/locales/en.js +1 -1
  251. package/dist/locales/en.js.map +1 -1
  252. package/dist/locales/es.js +1 -1
  253. package/dist/locales/es.js.map +1 -1
  254. package/dist/locales/ja.js +1 -1
  255. package/dist/locales/ja.js.map +1 -1
  256. package/dist/locales/ko.js +1 -1
  257. package/dist/locales/ko.js.map +1 -1
  258. package/dist/locales/zh.js +1 -1
  259. package/dist/locales/zh.js.map +1 -1
  260. package/dist/{offers.d.ts → product-list.d.ts} +5 -5
  261. package/dist/react.js +1 -1
  262. package/dist/styles.css +1 -1
  263. package/package.json +28 -6
  264. package/dist/client-Cxz_miQj.js.map +0 -1
  265. package/dist/hooks-aKefXeMO.js.map +0 -1
@@ -0,0 +1,1702 @@
1
+ import { E as e, S as t, c as n, p as r, r as i, s as a, w as o } from "./admin-utils-BK4Vh1o_.js";
2
+ import { t as s } from "./admin-button-CTL3DgOt.js";
3
+ import { t as c } from "./admin-input-CcfQfJFN.js";
4
+ import { t as l } from "./admin-skeleton-DsM7crYi.js";
5
+ import { s as u } from "./admin-capabilities-BuigAgtm.js";
6
+ import { c as d, d as f, l as p, n as m, o as h, s as g } from "./admin-format-DoohJ7Fg.js";
7
+ import { n as _ } from "./admin-confirm-katGq0Qo.js";
8
+ import { t as v } from "./admin-form-field-errors-hbUMIriS.js";
9
+ import { a as y, i as b, n as x, r as S, t as C } from "./admin-select-DBgprVW6.js";
10
+ import { n as w, r as T } from "./admin-dom-uMmZzRvU.js";
11
+ import { a as E, n as ee, o as te, r as D, s as O, t as k } from "./admin-table-CH9TrXJf.js";
12
+ import { t as ne } from "./admin-linked-table-row-BsaUruCN.js";
13
+ import { t as A } from "./admin-badge-DR5-1qd8.js";
14
+ import { a as re, i as ie, n as ae, o as oe, r as se, s as ce, t as le } from "./admin-dialog-BjuKI5Hp.js";
15
+ import { t as j } from "./admin-label-BiEN5cjb.js";
16
+ import { t as ue } from "./admin-switch-BJUxLCsa.js";
17
+ import { n as de, r as fe } from "./admin-dialog-width-BPrgdYlj.js";
18
+ import * as M from "react";
19
+ import { useMutation as pe, useQuery as me, useQueryClient as he } from "@tanstack/react-query";
20
+ import { Fragment as N, jsx as P, jsxs as F } from "react/jsx-runtime";
21
+ import { HugeiconsIcon as I } from "@hugeicons/react";
22
+ import { Activity01Icon as ge, Add01Icon as L, ArrowLeft01Icon as _e, ArrowRight01Icon as ve, Delete02Icon as R, Edit02Icon as z, InformationCircleIcon as ye, Money03Icon as be, Search01Icon as xe } from "@hugeicons/core-free-icons";
23
+ import { useForm as Se } from "@tanstack/react-form";
24
+ //#region src/admin/pages/catalog/metering-model.ts
25
+ var Ce = class extends Error {
26
+ fieldId;
27
+ constructor(e, t) {
28
+ super(t), this.name = "RateCardFormError", this.fieldId = e;
29
+ }
30
+ };
31
+ function we(e) {
32
+ return e.pending ? "loading" : e.error?.status === 403 ? "permission" : e.error ? "error" : e.count === 0 ? "empty" : "ready";
33
+ }
34
+ function Te(e) {
35
+ return e.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^[-_]+|[-_]+$/g, "");
36
+ }
37
+ function Ee(e) {
38
+ return {
39
+ key: e?.key ?? "",
40
+ eventType: e?.event_type ?? "",
41
+ aggregation: e?.aggregation === "count" ? "count" : "sum",
42
+ valueProperty: e?.value_property ?? "",
43
+ unit: e?.unit ?? "",
44
+ groupBy: Object.entries(e?.group_by ?? {}).map(([e, t]) => ({
45
+ key: e,
46
+ value: t
47
+ }))
48
+ };
49
+ }
50
+ function De(e) {
51
+ let t = Te(e.key);
52
+ if (!t) throw Error("Enter a meter key.");
53
+ let n = e.eventType.trim(), r = e.valueProperty.trim();
54
+ if (e.aggregation === "sum" && !r) throw Error("Sum meters require a value property.");
55
+ let i = Me(e.groupBy, "group");
56
+ return {
57
+ key: t,
58
+ meter: {
59
+ event_type: n,
60
+ aggregation: e.aggregation,
61
+ value_property: e.aggregation === "sum" ? r : "",
62
+ unit: e.unit.trim() || void 0,
63
+ group_by: i
64
+ }
65
+ };
66
+ }
67
+ function Oe(e) {
68
+ let t = e?.price, n = t?.per_unit?.matrix, r = e?.allowance, i = r?.included === void 0 ? "none" : "included", a = t?.currency ?? "USD";
69
+ return {
70
+ productId: e?.product_id ?? "",
71
+ model: t?.model && t.model !== "flat" ? t.model : "per_unit",
72
+ currency: a,
73
+ unitAmount: U(a, t?.per_unit?.unit_amount),
74
+ divideBy: W(t?.per_unit?.divide_by, "1"),
75
+ round: t?.per_unit?.round ?? "half_up",
76
+ maximumAmount: U(a, t?.per_unit?.maximum_amount),
77
+ matrixEnabled: !!n,
78
+ matrixDimension: n?.dimension ?? "",
79
+ matrixCells: Object.entries(n?.cells ?? {}).map(([e, t]) => ({
80
+ key: e,
81
+ unitAmount: U(a, t.unit_amount),
82
+ maximumAmount: U(a, t.maximum_amount)
83
+ })),
84
+ tierMode: "graduated",
85
+ tiers: (t?.tiered?.tiers ?? [{
86
+ up_to: null,
87
+ unit_amount: "0",
88
+ flat_amount: "0"
89
+ }]).map((e) => ({
90
+ upTo: e.up_to === null ? "" : String(e.up_to),
91
+ unitAmount: U(a, e.unit_amount),
92
+ flatAmount: U(a, e.flat_amount)
93
+ })),
94
+ packageAmount: U(a, t?.package?.amount),
95
+ packageSize: W(t?.package?.package_size, "1"),
96
+ freeUnits: W(t?.package?.free_units),
97
+ filters: Object.entries(e?.filter ?? {}).map(([e, t]) => ({
98
+ key: e,
99
+ value: t.join(", ")
100
+ })),
101
+ allowanceMode: i,
102
+ allowanceIncluded: W(r?.included)
103
+ };
104
+ }
105
+ function ke(e) {
106
+ e.productId || H("rate-product", "Select a product.");
107
+ let t = e.currency.trim().toUpperCase();
108
+ m(t) === void 0 && H("rate-currency", `Use a supported currency: ${f.join(", ")}.`);
109
+ let n = Ae(e, t), r = je(e);
110
+ return {
111
+ product_id: e.productId,
112
+ filter: Ne(e.filters),
113
+ price: n,
114
+ ...r ? { allowance: r } : {}
115
+ };
116
+ }
117
+ function Ae(e, t) {
118
+ if (e.model === "per_unit") {
119
+ let n = Pe(e.divideBy, "Divisor", "rate-divide-by"), r = V(t, e.maximumAmount, "Maximum amount", "rate-maximum");
120
+ if (e.matrixEnabled) {
121
+ let i = e.matrixDimension.trim();
122
+ i || H("matrix-dimension", "Select a matrix dimension."), e.matrixCells.length === 0 && H("matrix-add-cell", "Add at least one matrix cell.");
123
+ let a = {};
124
+ for (let [n, r] of e.matrixCells.entries()) {
125
+ let e = r.key.trim(), i = `matrix-cell-${n}`;
126
+ e || H(`${i}-value`, "Each matrix cell needs a value."), a[e] && H(`${i}-value`, `Duplicate matrix value “${e}”.`), a[e] = {
127
+ unit_amount: B(t, r.unitAmount, `Price for ${e}`, `${i}-unit-price`, !0),
128
+ ...V(t, r.maximumAmount, `Maximum for ${e}`, `${i}-maximum`) === "0" ? {} : { maximum_amount: V(t, r.maximumAmount, `Maximum for ${e}`, `${i}-maximum`) }
129
+ };
130
+ }
131
+ return {
132
+ model: "per_unit",
133
+ currency: t,
134
+ per_unit: {
135
+ divide_by: n,
136
+ round: e.round,
137
+ ...r === "0" ? {} : { maximum_amount: r },
138
+ matrix: {
139
+ dimension: i,
140
+ cells: a
141
+ }
142
+ }
143
+ };
144
+ }
145
+ return {
146
+ model: "per_unit",
147
+ currency: t,
148
+ per_unit: {
149
+ unit_amount: B(t, e.unitAmount, "Unit price", "rate-unit-amount", !0),
150
+ divide_by: n,
151
+ round: e.round,
152
+ ...r === "0" ? {} : { maximum_amount: r }
153
+ }
154
+ };
155
+ }
156
+ if (e.model === "tiered") {
157
+ e.tiers.length === 0 && H("tier-add", "Add at least one tier.");
158
+ let n = e.tiers.map((n, r) => {
159
+ let i = r === e.tiers.length - 1, a = n.upTo.trim();
160
+ return i && a && H(`tier-${r}-limit`, "The final tier must be unbounded."), !i && !a && H(`tier-${r}-limit`, "Only the final tier can be unbounded."), {
161
+ up_to: i ? null : Pe(a, `Tier ${r + 1} limit`, `tier-${r}-limit`),
162
+ unit_amount: B(t, n.unitAmount, `Tier ${r + 1} unit price`, `tier-${r}-unit-price`, !0),
163
+ flat_amount: V(t, n.flatAmount, `Tier ${r + 1} flat amount`, `tier-${r}-flat-amount`)
164
+ };
165
+ });
166
+ for (let e = 1; e < n.length - 1; e += 1) (n[e].up_to ?? 0) <= (n[e - 1].up_to ?? 0) && H(`tier-${e}-limit`, "Tier limits must increase.");
167
+ return {
168
+ model: "tiered",
169
+ currency: t,
170
+ tiered: {
171
+ mode: e.tierMode,
172
+ tiers: n
173
+ }
174
+ };
175
+ }
176
+ return {
177
+ model: "package",
178
+ currency: t,
179
+ package: {
180
+ amount: B(t, e.packageAmount, "Package price", "package-amount"),
181
+ package_size: Pe(e.packageSize, "Package size", "package-size"),
182
+ free_units: Fe(e.freeUnits, "Free units", "package-free")
183
+ }
184
+ };
185
+ }
186
+ function je(e) {
187
+ if (e.allowanceMode !== "none") return { included: Fe(e.allowanceIncluded, "Included allowance", "allowance-included") };
188
+ }
189
+ function Me(e, t) {
190
+ let n = {};
191
+ for (let r of e) {
192
+ let e = r.key.trim(), i = r.value.trim();
193
+ if (!e || !i) throw Error(`Each ${t} row needs both fields.`);
194
+ if (n[e]) throw Error(`Duplicate ${t} key “${e}”.`);
195
+ n[e] = i;
196
+ }
197
+ return n;
198
+ }
199
+ function Ne(e) {
200
+ let t = {};
201
+ for (let [n, r] of e.entries()) {
202
+ let e = r.key.trim(), i = [...new Set(r.value.split(",").map((e) => e.trim()))].filter(Boolean);
203
+ e || H(`filter-${n}-dimension`, "Select a dimension for this filter."), i.length === 0 && H(`filter-${n}-values`, "Enter at least one value for this filter."), t[e] && H(`filter-${n}-dimension`, `Duplicate filter dimension “${e}”.`), t[e] = i;
204
+ }
205
+ return t;
206
+ }
207
+ function B(e, t, n, r, i = !1) {
208
+ let a = d(t, e);
209
+ return (a === null || BigInt(a) < 0n || !i && BigInt(a) === 0n) && H(r, `${n} must be ${i ? "zero or more" : "greater than zero"}.`), a;
210
+ }
211
+ function V(e, t, n, r) {
212
+ return t.trim() ? B(e, t, n, r, !0) : "0";
213
+ }
214
+ function Pe(e, t, n) {
215
+ let r = Number(e);
216
+ return (!Number.isSafeInteger(r) || r <= 0) && H(n, `${t} must be a positive whole number.`), r;
217
+ }
218
+ function Fe(e, t, n) {
219
+ if (!e.trim()) return 0;
220
+ let r = Number(e);
221
+ return (!Number.isSafeInteger(r) || r < 0) && H(n, `${t} must be zero or a positive whole number.`), r;
222
+ }
223
+ function H(e, t) {
224
+ throw new Ce(e, t);
225
+ }
226
+ function U(e, t) {
227
+ return t && t !== "0" ? p(t, e) : "";
228
+ }
229
+ function W(e, t = "") {
230
+ return e ? String(e) : t;
231
+ }
232
+ function Ie(e) {
233
+ if (!e) return "Not priced";
234
+ let { price: t } = e, n = t.currency ?? "";
235
+ return t.model === "per_unit" && t.per_unit ? t.per_unit.matrix ? `${Object.keys(t.per_unit.matrix.cells ?? {}).length} matrix rates · ${n}` : `${g(t.per_unit.unit_amount ?? "0", n)} per ${t.per_unit.divide_by || 1} units` : t.model === "tiered" && t.tiered ? `${t.tiered.tiers?.length ?? 0} ${t.tiered.mode} tiers · ${n}` : t.model === "package" && t.package ? `${g(t.package.amount ?? "0", n)} per ${(t.package.package_size ?? 1).toLocaleString()} units` : `Unsupported price · ${n}`;
236
+ }
237
+ function Le(e, t) {
238
+ return t ? e.has_activity ? "Meter definitions lock after the first event." : null : "Catalog updates are disabled.";
239
+ }
240
+ //#endregion
241
+ //#region src/admin/pages/catalog/meter-form.tsx
242
+ function Re({ meter: t, writesAllowed: n }) {
243
+ let { toast: i, toastApiError: a, adminMutations: l } = r(), { id: u, text: d } = e(), [f, p] = M.useState(!1), [m, h] = M.useState(""), g = he(), _ = pe(l.putUsageMeter(g)), w = t ? Le(t, n) : null, T = Se({
244
+ defaultValues: Ee(t),
245
+ onSubmit: async ({ value: e }) => {
246
+ h("");
247
+ try {
248
+ let n = De(e);
249
+ n.meter.expected_revision = t?.revision ?? 0, await _.mutateAsync(n), i.success(t ? "Meter updated" : "Meter created"), p(!1), T.reset();
250
+ } catch (e) {
251
+ if (e instanceof Error && !("status" in e)) {
252
+ h(e.message);
253
+ return;
254
+ }
255
+ a(e, t ? "Update meter" : "Create meter");
256
+ }
257
+ }
258
+ });
259
+ return w ? /* @__PURE__ */ F(s, {
260
+ variant: "outline",
261
+ size: "sm",
262
+ disabled: !0,
263
+ title: w,
264
+ children: [/* @__PURE__ */ P(I, {
265
+ icon: z,
266
+ className: "size-4"
267
+ }), /* @__PURE__ */ P(o, { id: "Edit definition" })]
268
+ }) : /* @__PURE__ */ F(le, {
269
+ open: f,
270
+ onOpenChange: (e) => {
271
+ p(e), h(""), e || T.reset();
272
+ },
273
+ children: [/* @__PURE__ */ P(ce, { render: /* @__PURE__ */ F(s, {
274
+ variant: t ? "outline" : "default",
275
+ size: "sm",
276
+ children: [/* @__PURE__ */ P(I, {
277
+ icon: t ? z : L,
278
+ className: "size-4"
279
+ }), t ? "Edit definition" : "Create meter"]
280
+ }) }), /* @__PURE__ */ P(ae, {
281
+ className: de,
282
+ children: /* @__PURE__ */ F("form", {
283
+ className: "grid gap-5",
284
+ onSubmit: (e) => {
285
+ e.preventDefault(), e.stopPropagation(), T.handleSubmit();
286
+ },
287
+ children: [
288
+ /* @__PURE__ */ F(re, { children: [/* @__PURE__ */ P(oe, { children: t ? "Edit meter" : "Create meter" }), /* @__PURE__ */ P(se, { children: /* @__PURE__ */ P(o, { id: "Define the event fields OpenRails will aggregate. Your host still reports each event through the usage API." }) })] }),
289
+ /* @__PURE__ */ F("div", {
290
+ className: "grid gap-4",
291
+ children: [
292
+ /* @__PURE__ */ P(T.Field, {
293
+ name: "key",
294
+ validators: { onBlur: ({ value: e }) => e.trim() ? void 0 : "Enter a meter key." },
295
+ children: (e) => /* @__PURE__ */ F("div", {
296
+ className: "grid gap-1.5",
297
+ children: [
298
+ /* @__PURE__ */ P(j, {
299
+ htmlFor: u("meter-key"),
300
+ children: /* @__PURE__ */ P(o, { id: "Key" })
301
+ }),
302
+ /* @__PURE__ */ P(c, {
303
+ id: u("meter-key"),
304
+ value: e.state.value,
305
+ onChange: (t) => e.handleChange(t.target.value),
306
+ onBlur: e.handleBlur,
307
+ disabled: !!t,
308
+ placeholder: d("api-tokens"),
309
+ autoComplete: "off"
310
+ }),
311
+ /* @__PURE__ */ P("p", {
312
+ className: "text-xs text-muted-foreground",
313
+ children: /* @__PURE__ */ P(o, { id: "Stable identifier. It cannot be renamed after creation." })
314
+ }),
315
+ /* @__PURE__ */ P(v, { errors: e.state.meta.errors })
316
+ ]
317
+ })
318
+ }),
319
+ /* @__PURE__ */ F("div", {
320
+ className: "grid gap-4 sm:grid-cols-2",
321
+ children: [/* @__PURE__ */ P(T.Field, {
322
+ name: "eventType",
323
+ children: (e) => /* @__PURE__ */ F("div", {
324
+ className: "grid gap-1.5",
325
+ children: [
326
+ /* @__PURE__ */ P(j, {
327
+ htmlFor: u("meter-event-type"),
328
+ children: /* @__PURE__ */ P(o, { id: "Event type" })
329
+ }),
330
+ /* @__PURE__ */ P(c, {
331
+ id: u("meter-event-type"),
332
+ value: e.state.value,
333
+ onChange: (t) => e.handleChange(t.target.value),
334
+ placeholder: d("token.used"),
335
+ autoComplete: "off"
336
+ }),
337
+ /* @__PURE__ */ P("p", {
338
+ className: "text-xs text-muted-foreground",
339
+ children: /* @__PURE__ */ P(o, { id: "Leave blank to use the meter key." })
340
+ })
341
+ ]
342
+ })
343
+ }), /* @__PURE__ */ P(T.Field, {
344
+ name: "unit",
345
+ children: (e) => /* @__PURE__ */ F("div", {
346
+ className: "grid gap-1.5",
347
+ children: [
348
+ /* @__PURE__ */ P(j, {
349
+ htmlFor: u("meter-unit"),
350
+ children: /* @__PURE__ */ P(o, { id: "Unit" })
351
+ }),
352
+ /* @__PURE__ */ P(c, {
353
+ id: u("meter-unit"),
354
+ value: e.state.value,
355
+ onChange: (t) => e.handleChange(t.target.value),
356
+ placeholder: d("tokens"),
357
+ autoComplete: "off"
358
+ }),
359
+ /* @__PURE__ */ P("p", {
360
+ className: "text-xs text-muted-foreground",
361
+ children: /* @__PURE__ */ P(o, { id: "Human-readable quantity shown in billing." })
362
+ })
363
+ ]
364
+ })
365
+ })]
366
+ }),
367
+ /* @__PURE__ */ F("div", {
368
+ className: "grid gap-4 sm:grid-cols-2",
369
+ children: [/* @__PURE__ */ P(T.Field, {
370
+ name: "aggregation",
371
+ children: (e) => /* @__PURE__ */ F("div", {
372
+ className: "grid gap-1.5",
373
+ children: [/* @__PURE__ */ P(j, {
374
+ htmlFor: u("meter-aggregation"),
375
+ children: /* @__PURE__ */ P(o, { id: "Aggregation" })
376
+ }), /* @__PURE__ */ F(C, {
377
+ value: e.state.value,
378
+ onValueChange: (t) => e.handleChange(t),
379
+ children: [/* @__PURE__ */ P(b, {
380
+ id: u("meter-aggregation"),
381
+ className: "w-full",
382
+ children: /* @__PURE__ */ P(y, {})
383
+ }), /* @__PURE__ */ F(x, { children: [/* @__PURE__ */ P(S, {
384
+ value: "sum",
385
+ children: /* @__PURE__ */ P(o, { id: "Sum a numeric field" })
386
+ }), /* @__PURE__ */ P(S, {
387
+ value: "count",
388
+ children: /* @__PURE__ */ P(o, { id: "Count events" })
389
+ })] })]
390
+ })]
391
+ })
392
+ }), /* @__PURE__ */ P(T.Subscribe, {
393
+ selector: (e) => e.values.aggregation,
394
+ children: (e) => e === "sum" ? /* @__PURE__ */ P(T.Field, {
395
+ name: "valueProperty",
396
+ validators: { onBlur: ({ value: e }) => e.trim() ? void 0 : "Sum meters require a value property." },
397
+ children: (e) => /* @__PURE__ */ F("div", {
398
+ className: "grid gap-1.5",
399
+ children: [
400
+ /* @__PURE__ */ P(j, {
401
+ htmlFor: u("meter-value-property"),
402
+ children: /* @__PURE__ */ P(o, { id: "Value property" })
403
+ }),
404
+ /* @__PURE__ */ P(c, {
405
+ id: u("meter-value-property"),
406
+ value: e.state.value,
407
+ onChange: (t) => e.handleChange(t.target.value),
408
+ onBlur: e.handleBlur,
409
+ placeholder: d("tokens"),
410
+ autoComplete: "off"
411
+ }),
412
+ /* @__PURE__ */ P(v, { errors: e.state.meta.errors })
413
+ ]
414
+ })
415
+ }) : /* @__PURE__ */ P("div", {
416
+ className: "self-end rounded-lg bg-muted/50 px-3 py-2 text-xs text-muted-foreground",
417
+ children: /* @__PURE__ */ P(o, { id: "Count uses one unit for every matching event." })
418
+ })
419
+ })]
420
+ }),
421
+ /* @__PURE__ */ P(T.Field, {
422
+ name: "groupBy",
423
+ mode: "array",
424
+ children: (e) => /* @__PURE__ */ F("fieldset", {
425
+ className: "grid gap-2",
426
+ children: [/* @__PURE__ */ F("div", {
427
+ className: "flex items-center justify-between gap-3",
428
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P(j, { children: /* @__PURE__ */ P(o, { id: "Dimensions" }) }), /* @__PURE__ */ P("p", {
429
+ className: "text-xs text-muted-foreground",
430
+ children: /* @__PURE__ */ P(o, { id: "Register event properties used by filters or matrix rates." })
431
+ })] }), /* @__PURE__ */ F(s, {
432
+ type: "button",
433
+ variant: "outline",
434
+ size: "sm",
435
+ onClick: () => e.pushValue({
436
+ key: "",
437
+ value: ""
438
+ }),
439
+ children: [/* @__PURE__ */ P(I, {
440
+ icon: L,
441
+ className: "size-4"
442
+ }), /* @__PURE__ */ P(o, { id: "Add dimension" })]
443
+ })]
444
+ }), e.state.value.map((t, n) => /* @__PURE__ */ F("div", {
445
+ className: "grid grid-cols-[1fr_1fr_auto] gap-2",
446
+ children: [
447
+ /* @__PURE__ */ P(c, {
448
+ "aria-label": `Dimension ${n + 1} name`,
449
+ value: t.key,
450
+ onChange: (e) => T.setFieldValue(`groupBy[${n}].key`, e.target.value),
451
+ placeholder: d("model"),
452
+ autoComplete: "off"
453
+ }),
454
+ /* @__PURE__ */ P(c, {
455
+ "aria-label": `Dimension ${n + 1} property`,
456
+ value: t.value,
457
+ onChange: (e) => T.setFieldValue(`groupBy[${n}].value`, e.target.value),
458
+ placeholder: d("metadata.model"),
459
+ autoComplete: "off"
460
+ }),
461
+ /* @__PURE__ */ P(s, {
462
+ type: "button",
463
+ variant: "ghost",
464
+ size: "icon",
465
+ "aria-label": `Remove dimension ${n + 1}`,
466
+ onClick: () => e.removeValue(n),
467
+ children: /* @__PURE__ */ P(I, {
468
+ icon: R,
469
+ className: "size-4"
470
+ })
471
+ })
472
+ ]
473
+ }, n))]
474
+ })
475
+ })
476
+ ]
477
+ }),
478
+ m && /* @__PURE__ */ P("p", {
479
+ role: "alert",
480
+ className: "text-sm text-destructive",
481
+ children: m
482
+ }),
483
+ /* @__PURE__ */ F(ie, { children: [/* @__PURE__ */ P(s, {
484
+ type: "button",
485
+ variant: "outline",
486
+ onClick: () => p(!1),
487
+ children: /* @__PURE__ */ P(o, { id: "Cancel" })
488
+ }), /* @__PURE__ */ P(T.Subscribe, {
489
+ selector: (e) => e.isSubmitting,
490
+ children: (e) => /* @__PURE__ */ P(s, {
491
+ type: "submit",
492
+ disabled: e || _.isPending,
493
+ children: e || _.isPending ? "Saving…" : "Save meter"
494
+ })
495
+ })] })
496
+ ]
497
+ })
498
+ })]
499
+ });
500
+ }
501
+ //#endregion
502
+ //#region src/admin/pages/catalog/rate-card-editor.tsx
503
+ var G = M.createContext(null);
504
+ function ze({ meter: t, writesAllowed: n = !1, products: a, productsPending: l = !1, productsError: u = !1, productsForbidden: d = !1 }) {
505
+ let { toast: f, toastApiError: p, adminMutations: m } = r(), { id: h, text: g } = e(), [v, w] = M.useState(!1), [T, E] = M.useState(null), ee = _(), te = he(), D = pe(m.putDefaultUsageRateCard(te)), O = a.filter((e) => !e.archived), k = t.rate_card, ne = D.isPending, A = Se({
506
+ defaultValues: Oe(k),
507
+ onSubmit: async ({ value: e }) => {
508
+ E(null);
509
+ try {
510
+ let t = ke(e);
511
+ if (k && !await ee({
512
+ title: "Replace the default rate?",
513
+ description: "Billed usage orders and amounts already accrued do not change. The new rate can only affect the remaining positive delta in the current unfinalized period and future periods.",
514
+ confirmLabel: "Replace rate",
515
+ cancelLabel: "Keep current rate"
516
+ })) return;
517
+ await ue(t);
518
+ } catch (e) {
519
+ if (e instanceof Ce) {
520
+ E({
521
+ fieldId: e.fieldId,
522
+ message: e.message
523
+ }), requestAnimationFrame(() => {
524
+ document.getElementById(h(e.fieldId))?.focus();
525
+ });
526
+ return;
527
+ }
528
+ p(e, "Save rate card");
529
+ }
530
+ }
531
+ }), ue = async (e) => {
532
+ try {
533
+ await D.mutateAsync({
534
+ meter: t,
535
+ rateCard: e
536
+ }), f.success(k ? "Default rate replaced" : "Default rate added"), w(!1);
537
+ } catch (e) {
538
+ p(e, "Save default rate");
539
+ }
540
+ };
541
+ return !n || !t.billing_supported ? null : /* @__PURE__ */ P(G.Provider, {
542
+ value: T,
543
+ children: /* @__PURE__ */ F(le, {
544
+ open: v,
545
+ onOpenChange: (e) => {
546
+ w(e), E(null), e || A.reset();
547
+ },
548
+ children: [/* @__PURE__ */ P(ce, { render: /* @__PURE__ */ F(s, {
549
+ variant: k ? "outline" : "default",
550
+ size: "sm",
551
+ children: [/* @__PURE__ */ P(I, {
552
+ icon: k ? z : be,
553
+ className: "size-4"
554
+ }), k ? "Edit default rate" : "Add default rate"]
555
+ }) }), /* @__PURE__ */ P(ae, {
556
+ className: `${fe} max-h-[calc(100dvh-2rem)] overflow-y-auto`,
557
+ children: /* @__PURE__ */ F("form", {
558
+ className: "grid gap-6",
559
+ onChange: () => E(null),
560
+ onSubmit: (e) => {
561
+ e.preventDefault(), e.stopPropagation(), A.handleSubmit();
562
+ },
563
+ children: [
564
+ /* @__PURE__ */ F(re, { children: [/* @__PURE__ */ P(oe, { children: k ? "Edit default rate" : "Add default rate" }), /* @__PURE__ */ P(se, { children: /* @__PURE__ */ P(o, { id: "Set the price that charges every customer's usage as it is recorded. Money is entered in major currency units." }) })] }),
565
+ /* @__PURE__ */ F("section", {
566
+ className: "grid gap-4",
567
+ children: [/* @__PURE__ */ P("h3", {
568
+ className: "text-sm font-medium",
569
+ children: /* @__PURE__ */ P(o, { id: "Product and model" })
570
+ }), l ? /* @__PURE__ */ P("div", {
571
+ className: "rounded-lg bg-muted/50 p-3 text-sm text-muted-foreground",
572
+ children: /* @__PURE__ */ P(o, { id: "Loading products…" })
573
+ }) : u ? /* @__PURE__ */ P("div", {
574
+ role: "alert",
575
+ className: "rounded-lg bg-muted/50 p-3 text-sm text-destructive",
576
+ children: d ? "Your role cannot read products for this merchant." : "Products could not be loaded. Close this form and try again."
577
+ }) : O.length === 0 ? /* @__PURE__ */ F("div", {
578
+ className: "rounded-lg bg-muted/50 p-3 text-sm",
579
+ children: [/* @__PURE__ */ P("p", { children: /* @__PURE__ */ P(o, { id: "No active products are available." }) }), /* @__PURE__ */ P(i, {
580
+ className: "text-primary underline underline-offset-3",
581
+ to: "/catalog",
582
+ children: /* @__PURE__ */ P(o, { id: "Create or activate a product first" })
583
+ })]
584
+ }) : /* @__PURE__ */ F("div", {
585
+ className: "grid gap-4 sm:grid-cols-3",
586
+ children: [
587
+ /* @__PURE__ */ P(A.Field, {
588
+ name: "productId",
589
+ children: (e) => /* @__PURE__ */ F("div", {
590
+ className: "grid gap-1.5 sm:col-span-2",
591
+ children: [
592
+ /* @__PURE__ */ P(j, {
593
+ htmlFor: h("rate-product"),
594
+ children: /* @__PURE__ */ P(o, { id: "Product" })
595
+ }),
596
+ /* @__PURE__ */ F(C, {
597
+ value: e.state.value || null,
598
+ onValueChange: (t) => e.handleChange(t ?? ""),
599
+ children: [/* @__PURE__ */ P(b, {
600
+ id: h("rate-product"),
601
+ className: "w-full",
602
+ ...Y("rate-product", T),
603
+ children: /* @__PURE__ */ P(y, { placeholder: g("Select product") })
604
+ }), /* @__PURE__ */ P(x, { children: O.map((e) => /* @__PURE__ */ P(S, {
605
+ value: e.id,
606
+ children: e.display_name
607
+ }, e.id)) })]
608
+ }),
609
+ /* @__PURE__ */ P(X, { fieldId: "rate-product" })
610
+ ]
611
+ })
612
+ }),
613
+ /* @__PURE__ */ P(A.Field, {
614
+ name: "currency",
615
+ children: (e) => /* @__PURE__ */ F("div", {
616
+ className: "grid gap-1.5",
617
+ children: [
618
+ /* @__PURE__ */ P(j, {
619
+ htmlFor: h("rate-currency"),
620
+ children: /* @__PURE__ */ P(o, { id: "Currency" })
621
+ }),
622
+ /* @__PURE__ */ P(c, {
623
+ id: h("rate-currency"),
624
+ value: e.state.value,
625
+ onChange: (t) => e.handleChange(t.target.value.toUpperCase()),
626
+ maxLength: 3,
627
+ placeholder: g("USD"),
628
+ className: "uppercase",
629
+ autoComplete: "off",
630
+ ...Y("rate-currency", T)
631
+ }),
632
+ /* @__PURE__ */ P(X, { fieldId: "rate-currency" })
633
+ ]
634
+ })
635
+ }),
636
+ /* @__PURE__ */ P(Be, { form: A })
637
+ ]
638
+ })]
639
+ }),
640
+ /* @__PURE__ */ P(A.Subscribe, {
641
+ selector: (e) => e.values.model,
642
+ children: (e) => /* @__PURE__ */ F("section", {
643
+ className: "grid gap-4 border-t pt-5",
644
+ children: [
645
+ /* @__PURE__ */ P("h3", {
646
+ className: "text-sm font-medium",
647
+ children: /* @__PURE__ */ P(o, { id: "Rate" })
648
+ }),
649
+ e === "per_unit" && /* @__PURE__ */ P(Ve, {
650
+ form: A,
651
+ meter: t
652
+ }),
653
+ e === "tiered" && /* @__PURE__ */ P(Ue, { form: A }),
654
+ e === "package" && /* @__PURE__ */ P(We, { form: A })
655
+ ]
656
+ })
657
+ }),
658
+ /* @__PURE__ */ P(Ge, {
659
+ form: A,
660
+ meter: t
661
+ }),
662
+ /* @__PURE__ */ P(Ke, { form: A }),
663
+ /* @__PURE__ */ P(A.Subscribe, {
664
+ selector: (e) => e.values,
665
+ children: (e) => /* @__PURE__ */ P(qe, { values: e })
666
+ }),
667
+ T && /* @__PURE__ */ P("p", {
668
+ role: "alert",
669
+ className: "text-sm text-destructive",
670
+ children: T.message
671
+ }),
672
+ /* @__PURE__ */ F(ie, { children: [/* @__PURE__ */ P(s, {
673
+ type: "button",
674
+ variant: "outline",
675
+ onClick: () => w(!1),
676
+ children: /* @__PURE__ */ P(o, { id: "Cancel" })
677
+ }), /* @__PURE__ */ P(s, {
678
+ type: "submit",
679
+ disabled: ne || l || u || O.length === 0,
680
+ children: ne ? "Saving…" : k ? "Review replacement" : "Save default rate"
681
+ })] })
682
+ ]
683
+ })
684
+ })]
685
+ })
686
+ });
687
+ }
688
+ function Be({ form: t }) {
689
+ let { id: n } = e();
690
+ return /* @__PURE__ */ P(t.Field, {
691
+ name: "model",
692
+ children: (e) => /* @__PURE__ */ F("div", {
693
+ className: "grid gap-1.5 sm:col-span-3",
694
+ children: [/* @__PURE__ */ P(j, {
695
+ htmlFor: n("rate-model"),
696
+ children: /* @__PURE__ */ P(o, { id: "Pricing model" })
697
+ }), /* @__PURE__ */ F(C, {
698
+ value: e.state.value,
699
+ onValueChange: (t) => e.handleChange(t),
700
+ children: [/* @__PURE__ */ P(b, {
701
+ id: n("rate-model"),
702
+ className: "w-full",
703
+ children: /* @__PURE__ */ P(y, {})
704
+ }), /* @__PURE__ */ F(x, { children: [
705
+ /* @__PURE__ */ P(S, {
706
+ value: "per_unit",
707
+ children: /* @__PURE__ */ P(o, { id: "Per unit" })
708
+ }),
709
+ /* @__PURE__ */ P(S, {
710
+ value: "tiered",
711
+ children: /* @__PURE__ */ P(o, { id: "Tiered" })
712
+ }),
713
+ /* @__PURE__ */ P(S, {
714
+ value: "package",
715
+ children: /* @__PURE__ */ P(o, { id: "Package" })
716
+ })
717
+ ] })]
718
+ })]
719
+ })
720
+ });
721
+ }
722
+ function Ve({ form: t, meter: n }) {
723
+ let { id: r, text: i } = e();
724
+ return /* @__PURE__ */ F(N, { children: [
725
+ /* @__PURE__ */ P(t.Field, {
726
+ name: "matrixEnabled",
727
+ children: (e) => /* @__PURE__ */ F("div", {
728
+ className: "flex items-center justify-between gap-4 rounded-lg bg-muted/50 px-3 py-2.5",
729
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P(j, {
730
+ htmlFor: r("rate-matrix"),
731
+ children: /* @__PURE__ */ P(o, { id: "Use matrix rates" })
732
+ }), /* @__PURE__ */ P("p", {
733
+ className: "text-xs text-muted-foreground",
734
+ children: /* @__PURE__ */ P(o, { id: "Price each value of one registered dimension separately." })
735
+ })] }), /* @__PURE__ */ P(ue, {
736
+ id: r("rate-matrix"),
737
+ checked: e.state.value,
738
+ onCheckedChange: e.handleChange,
739
+ disabled: Object.keys(n.group_by ?? {}).length === 0
740
+ })]
741
+ })
742
+ }),
743
+ /* @__PURE__ */ P(t.Subscribe, {
744
+ selector: (e) => e.values.matrixEnabled,
745
+ children: (e) => e ? /* @__PURE__ */ P(He, {
746
+ form: t,
747
+ meter: n
748
+ }) : /* @__PURE__ */ P(t.Field, {
749
+ name: "unitAmount",
750
+ children: (e) => /* @__PURE__ */ P(q, {
751
+ id: "rate-unit-amount",
752
+ label: i("Price per divisor"),
753
+ value: e.state.value,
754
+ onChange: e.handleChange,
755
+ placeholder: "0.0025"
756
+ })
757
+ })
758
+ }),
759
+ /* @__PURE__ */ F("div", {
760
+ className: "grid gap-4 sm:grid-cols-3",
761
+ children: [
762
+ /* @__PURE__ */ P(t.Field, {
763
+ name: "divideBy",
764
+ children: (e) => /* @__PURE__ */ P(K, {
765
+ id: "rate-divide-by",
766
+ label: i("Divisor"),
767
+ value: e.state.value,
768
+ onChange: e.handleChange,
769
+ inputMode: "numeric",
770
+ placeholder: "1"
771
+ })
772
+ }),
773
+ /* @__PURE__ */ P(t.Field, {
774
+ name: "round",
775
+ children: (e) => /* @__PURE__ */ F("div", {
776
+ className: "grid gap-1.5",
777
+ children: [/* @__PURE__ */ P(j, {
778
+ htmlFor: r("rate-round"),
779
+ children: /* @__PURE__ */ P(o, { id: "Rounding" })
780
+ }), /* @__PURE__ */ F(C, {
781
+ value: e.state.value,
782
+ onValueChange: (t) => e.handleChange(t),
783
+ children: [/* @__PURE__ */ P(b, {
784
+ id: r("rate-round"),
785
+ className: "w-full",
786
+ children: /* @__PURE__ */ P(y, {})
787
+ }), /* @__PURE__ */ F(x, { children: [
788
+ /* @__PURE__ */ P(S, {
789
+ value: "half_up",
790
+ children: /* @__PURE__ */ P(o, { id: "Nearest" })
791
+ }),
792
+ /* @__PURE__ */ P(S, {
793
+ value: "up",
794
+ children: /* @__PURE__ */ P(o, { id: "Up" })
795
+ }),
796
+ /* @__PURE__ */ P(S, {
797
+ value: "down",
798
+ children: /* @__PURE__ */ P(o, { id: "Down" })
799
+ })
800
+ ] })]
801
+ })]
802
+ })
803
+ }),
804
+ /* @__PURE__ */ P(t.Field, {
805
+ name: "maximumAmount",
806
+ children: (e) => /* @__PURE__ */ P(q, {
807
+ id: "rate-maximum",
808
+ label: i("Period maximum"),
809
+ value: e.state.value,
810
+ onChange: e.handleChange,
811
+ placeholder: i("No maximum")
812
+ })
813
+ })
814
+ ]
815
+ })
816
+ ] });
817
+ }
818
+ function He({ form: t, meter: n }) {
819
+ let { id: r, text: i } = e(), a = M.useContext(G);
820
+ return /* @__PURE__ */ F(N, { children: [/* @__PURE__ */ P(t.Field, {
821
+ name: "matrixDimension",
822
+ children: (e) => /* @__PURE__ */ F("div", {
823
+ className: "grid gap-1.5",
824
+ children: [
825
+ /* @__PURE__ */ P(j, {
826
+ htmlFor: r("matrix-dimension"),
827
+ children: /* @__PURE__ */ P(o, { id: "Dimension" })
828
+ }),
829
+ /* @__PURE__ */ F(C, {
830
+ value: e.state.value || null,
831
+ onValueChange: (t) => e.handleChange(t ?? ""),
832
+ children: [/* @__PURE__ */ P(b, {
833
+ id: r("matrix-dimension"),
834
+ className: "w-full",
835
+ ...Y("matrix-dimension", a),
836
+ children: /* @__PURE__ */ P(y, { placeholder: i("Select dimension") })
837
+ }), /* @__PURE__ */ P(x, { children: Object.keys(n.group_by ?? {}).map((e) => /* @__PURE__ */ P(S, {
838
+ value: e,
839
+ children: e
840
+ }, e)) })]
841
+ }),
842
+ /* @__PURE__ */ P(X, { fieldId: "matrix-dimension" })
843
+ ]
844
+ })
845
+ }), /* @__PURE__ */ P(t.Field, {
846
+ name: "matrixCells",
847
+ mode: "array",
848
+ children: (e) => /* @__PURE__ */ F("div", {
849
+ className: "grid gap-2",
850
+ children: [
851
+ /* @__PURE__ */ F("div", {
852
+ className: "flex items-center justify-between gap-3",
853
+ children: [/* @__PURE__ */ P(j, { children: /* @__PURE__ */ P(o, { id: "Matrix cells" }) }), /* @__PURE__ */ F(s, {
854
+ id: r("matrix-add-cell"),
855
+ type: "button",
856
+ variant: "outline",
857
+ size: "sm",
858
+ onClick: () => e.pushValue({
859
+ key: "",
860
+ unitAmount: "",
861
+ maximumAmount: ""
862
+ }),
863
+ children: [/* @__PURE__ */ P(I, {
864
+ icon: L,
865
+ className: "size-4"
866
+ }), /* @__PURE__ */ P(o, { id: "Add cell" })]
867
+ })]
868
+ }),
869
+ /* @__PURE__ */ P(X, { fieldId: "matrix-add-cell" }),
870
+ e.state.value.length > 0 && /* @__PURE__ */ F("div", {
871
+ className: "hidden gap-2 px-0.5 text-xs text-muted-foreground sm:grid sm:grid-cols-[1fr_1fr_1fr_auto]",
872
+ children: [
873
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Value" }) }),
874
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Unit price" }) }),
875
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Maximum" }) }),
876
+ /* @__PURE__ */ P("span", {
877
+ className: "size-8",
878
+ "aria-hidden": "true"
879
+ })
880
+ ]
881
+ }),
882
+ e.state.value.map((n, r) => /* @__PURE__ */ F("div", {
883
+ className: "grid gap-2 sm:grid-cols-[1fr_1fr_1fr_auto]",
884
+ children: [
885
+ /* @__PURE__ */ P(J, {
886
+ id: `matrix-cell-${r}-value`,
887
+ label: i("Value"),
888
+ value: n.key,
889
+ onChange: (e) => t.setFieldValue(`matrixCells[${r}].key`, e),
890
+ placeholder: i("gpt-5")
891
+ }),
892
+ /* @__PURE__ */ P(J, {
893
+ id: `matrix-cell-${r}-unit-price`,
894
+ label: i("Unit price"),
895
+ value: n.unitAmount,
896
+ onChange: (e) => t.setFieldValue(`matrixCells[${r}].unitAmount`, e),
897
+ inputMode: "decimal",
898
+ placeholder: i("Price")
899
+ }),
900
+ /* @__PURE__ */ P(J, {
901
+ id: `matrix-cell-${r}-maximum`,
902
+ label: i("Maximum"),
903
+ value: n.maximumAmount,
904
+ onChange: (e) => t.setFieldValue(`matrixCells[${r}].maximumAmount`, e),
905
+ inputMode: "decimal",
906
+ placeholder: i("Maximum")
907
+ }),
908
+ /* @__PURE__ */ P(Ye, {
909
+ label: `Remove matrix cell ${r + 1}`,
910
+ onClick: () => e.removeValue(r)
911
+ })
912
+ ]
913
+ }, r))
914
+ ]
915
+ })
916
+ })] });
917
+ }
918
+ function Ue({ form: t }) {
919
+ let { id: n, text: r } = e();
920
+ return /* @__PURE__ */ P(N, { children: /* @__PURE__ */ P(t.Field, {
921
+ name: "tiers",
922
+ mode: "array",
923
+ children: (e) => /* @__PURE__ */ F("div", {
924
+ className: "grid gap-2",
925
+ children: [
926
+ /* @__PURE__ */ F("div", {
927
+ className: "flex items-center justify-between gap-3",
928
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P(j, { children: /* @__PURE__ */ P(o, { id: "Tiers" }) }), /* @__PURE__ */ P("p", {
929
+ className: "text-xs text-muted-foreground",
930
+ children: /* @__PURE__ */ P(o, { id: "Leave the final limit blank for the unbounded tier." })
931
+ })] }), /* @__PURE__ */ F(s, {
932
+ id: n("tier-add"),
933
+ type: "button",
934
+ variant: "outline",
935
+ size: "sm",
936
+ onClick: () => e.pushValue({
937
+ upTo: "",
938
+ unitAmount: "",
939
+ flatAmount: ""
940
+ }),
941
+ children: [/* @__PURE__ */ P(I, {
942
+ icon: L,
943
+ className: "size-4"
944
+ }), /* @__PURE__ */ P(o, { id: "Add tier" })]
945
+ })]
946
+ }),
947
+ /* @__PURE__ */ P(X, { fieldId: "tier-add" }),
948
+ e.state.value.length > 0 && /* @__PURE__ */ F("div", {
949
+ className: "hidden gap-2 px-0.5 text-xs text-muted-foreground sm:grid sm:grid-cols-[1fr_1fr_1fr_auto]",
950
+ children: [
951
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Upper limit" }) }),
952
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Unit price" }) }),
953
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Flat amount" }) }),
954
+ /* @__PURE__ */ P("span", {
955
+ className: "size-8",
956
+ "aria-hidden": "true"
957
+ })
958
+ ]
959
+ }),
960
+ e.state.value.map((n, i) => /* @__PURE__ */ F("div", {
961
+ className: "grid gap-2 sm:grid-cols-[1fr_1fr_1fr_auto]",
962
+ children: [
963
+ /* @__PURE__ */ P(J, {
964
+ id: `tier-${i}-limit`,
965
+ label: r("Upper limit"),
966
+ value: n.upTo,
967
+ onChange: (e) => t.setFieldValue(`tiers[${i}].upTo`, e),
968
+ inputMode: "numeric",
969
+ placeholder: i === e.state.value.length - 1 ? "No limit" : "Up to"
970
+ }),
971
+ /* @__PURE__ */ P(J, {
972
+ id: `tier-${i}-unit-price`,
973
+ label: r("Unit price"),
974
+ value: n.unitAmount,
975
+ onChange: (e) => t.setFieldValue(`tiers[${i}].unitAmount`, e),
976
+ inputMode: "decimal",
977
+ placeholder: r("Unit price")
978
+ }),
979
+ /* @__PURE__ */ P(J, {
980
+ id: `tier-${i}-flat-amount`,
981
+ label: r("Flat amount"),
982
+ value: n.flatAmount,
983
+ onChange: (e) => t.setFieldValue(`tiers[${i}].flatAmount`, e),
984
+ inputMode: "decimal",
985
+ placeholder: r("Flat amount")
986
+ }),
987
+ /* @__PURE__ */ P(Ye, {
988
+ label: `Remove tier ${i + 1}`,
989
+ onClick: () => e.removeValue(i),
990
+ disabled: e.state.value.length === 1
991
+ })
992
+ ]
993
+ }, i))
994
+ ]
995
+ })
996
+ }) });
997
+ }
998
+ function We({ form: t }) {
999
+ let { text: n } = e();
1000
+ return /* @__PURE__ */ F("div", {
1001
+ className: "grid gap-4 sm:grid-cols-3",
1002
+ children: [
1003
+ /* @__PURE__ */ P(t.Field, {
1004
+ name: "packageAmount",
1005
+ children: (e) => /* @__PURE__ */ P(q, {
1006
+ id: "package-amount",
1007
+ label: n("Package price"),
1008
+ value: e.state.value,
1009
+ onChange: e.handleChange,
1010
+ placeholder: "10.00"
1011
+ })
1012
+ }),
1013
+ /* @__PURE__ */ P(t.Field, {
1014
+ name: "packageSize",
1015
+ children: (e) => /* @__PURE__ */ P(K, {
1016
+ id: "package-size",
1017
+ label: n("Units per package"),
1018
+ value: e.state.value,
1019
+ onChange: e.handleChange,
1020
+ inputMode: "numeric",
1021
+ placeholder: "1000"
1022
+ })
1023
+ }),
1024
+ /* @__PURE__ */ P(t.Field, {
1025
+ name: "freeUnits",
1026
+ children: (e) => /* @__PURE__ */ P(K, {
1027
+ id: "package-free",
1028
+ label: n("Free units"),
1029
+ value: e.state.value,
1030
+ onChange: e.handleChange,
1031
+ inputMode: "numeric",
1032
+ placeholder: "0"
1033
+ })
1034
+ })
1035
+ ]
1036
+ });
1037
+ }
1038
+ function Ge({ form: t, meter: n }) {
1039
+ let { id: r, text: i } = e(), a = M.useContext(G);
1040
+ return /* @__PURE__ */ F("section", {
1041
+ className: "grid gap-3 border-t pt-5",
1042
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("h3", {
1043
+ className: "text-sm font-medium",
1044
+ children: /* @__PURE__ */ P(o, { id: "Event filters" })
1045
+ }), /* @__PURE__ */ P("p", {
1046
+ className: "text-xs text-muted-foreground",
1047
+ children: /* @__PURE__ */ P(o, { id: "Optional. Only events with one of the listed dimension values are rated." })
1048
+ })] }), /* @__PURE__ */ P(t.Field, {
1049
+ name: "filters",
1050
+ mode: "array",
1051
+ children: (e) => /* @__PURE__ */ F("div", {
1052
+ className: "grid gap-2",
1053
+ children: [
1054
+ e.state.value.length > 0 && /* @__PURE__ */ F("div", {
1055
+ className: "hidden gap-2 px-0.5 text-xs text-muted-foreground sm:grid sm:grid-cols-[1fr_2fr_auto]",
1056
+ children: [
1057
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Dimension" }) }),
1058
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(o, { id: "Values" }) }),
1059
+ /* @__PURE__ */ P("span", {
1060
+ className: "size-8",
1061
+ "aria-hidden": "true"
1062
+ })
1063
+ ]
1064
+ }),
1065
+ e.state.value.map((s, c) => /* @__PURE__ */ F("div", {
1066
+ className: "grid gap-2 sm:grid-cols-[1fr_2fr_auto]",
1067
+ children: [
1068
+ /* @__PURE__ */ F("div", {
1069
+ className: "grid gap-1.5",
1070
+ children: [
1071
+ /* @__PURE__ */ P(j, {
1072
+ htmlFor: r(`filter-${c}-dimension`),
1073
+ className: "text-xs text-muted-foreground sm:sr-only",
1074
+ children: /* @__PURE__ */ P(o, { id: "Dimension" })
1075
+ }),
1076
+ /* @__PURE__ */ F(C, {
1077
+ value: s.key || null,
1078
+ onValueChange: (e) => t.setFieldValue(`filters[${c}].key`, e ?? ""),
1079
+ children: [/* @__PURE__ */ P(b, {
1080
+ id: r(`filter-${c}-dimension`),
1081
+ className: "w-full",
1082
+ ...Y(`filter-${c}-dimension`, a),
1083
+ children: /* @__PURE__ */ P(y, { placeholder: i("Dimension") })
1084
+ }), /* @__PURE__ */ P(x, { children: Object.keys(n.group_by ?? {}).map((e) => /* @__PURE__ */ P(S, {
1085
+ value: e,
1086
+ children: e
1087
+ }, e)) })]
1088
+ }),
1089
+ /* @__PURE__ */ P(X, { fieldId: `filter-${c}-dimension` })
1090
+ ]
1091
+ }),
1092
+ /* @__PURE__ */ P(J, {
1093
+ id: `filter-${c}-values`,
1094
+ label: i("Values"),
1095
+ value: s.value,
1096
+ onChange: (e) => t.setFieldValue(`filters[${c}].value`, e),
1097
+ placeholder: i("eu, us")
1098
+ }),
1099
+ /* @__PURE__ */ P(Ye, {
1100
+ label: `Remove filter ${c + 1}`,
1101
+ onClick: () => e.removeValue(c)
1102
+ })
1103
+ ]
1104
+ }, c)),
1105
+ /* @__PURE__ */ F(s, {
1106
+ type: "button",
1107
+ variant: "outline",
1108
+ size: "sm",
1109
+ className: "w-fit",
1110
+ disabled: Object.keys(n.group_by ?? {}).length === 0,
1111
+ onClick: () => e.pushValue({
1112
+ key: "",
1113
+ value: ""
1114
+ }),
1115
+ children: [/* @__PURE__ */ P(I, {
1116
+ icon: L,
1117
+ className: "size-4"
1118
+ }), /* @__PURE__ */ P(o, { id: "Add filter" })]
1119
+ })
1120
+ ]
1121
+ })
1122
+ })]
1123
+ });
1124
+ }
1125
+ function Ke({ form: t }) {
1126
+ let { id: n, text: r } = e();
1127
+ return /* @__PURE__ */ F("section", {
1128
+ className: "grid gap-4 border-t pt-5",
1129
+ children: [
1130
+ /* @__PURE__ */ P("h3", {
1131
+ className: "text-sm font-medium",
1132
+ children: /* @__PURE__ */ P(o, { id: "Allowance" })
1133
+ }),
1134
+ /* @__PURE__ */ P(t.Field, {
1135
+ name: "allowanceMode",
1136
+ children: (e) => /* @__PURE__ */ F("div", {
1137
+ className: "grid gap-1.5",
1138
+ children: [/* @__PURE__ */ P(j, {
1139
+ htmlFor: n("allowance-mode"),
1140
+ children: /* @__PURE__ */ P(o, { id: "Included usage" })
1141
+ }), /* @__PURE__ */ F(C, {
1142
+ value: e.state.value,
1143
+ onValueChange: (t) => e.handleChange(t),
1144
+ children: [/* @__PURE__ */ P(b, {
1145
+ id: n("allowance-mode"),
1146
+ className: "w-full",
1147
+ children: /* @__PURE__ */ P(y, {})
1148
+ }), /* @__PURE__ */ F(x, { children: [/* @__PURE__ */ P(S, {
1149
+ value: "none",
1150
+ children: /* @__PURE__ */ P(o, { id: "No allowance" })
1151
+ }), /* @__PURE__ */ P(S, {
1152
+ value: "included",
1153
+ children: /* @__PURE__ */ P(o, { id: "Fixed included units" })
1154
+ })] })]
1155
+ })]
1156
+ })
1157
+ }),
1158
+ /* @__PURE__ */ P(t.Subscribe, {
1159
+ selector: (e) => e.values.allowanceMode,
1160
+ children: (e) => e === "included" ? /* @__PURE__ */ P(t.Field, {
1161
+ name: "allowanceIncluded",
1162
+ children: (e) => /* @__PURE__ */ P(K, {
1163
+ id: "allowance-included",
1164
+ label: r("Included units per period"),
1165
+ value: e.state.value,
1166
+ onChange: e.handleChange,
1167
+ inputMode: "numeric",
1168
+ placeholder: "1000"
1169
+ })
1170
+ }) : null
1171
+ })
1172
+ ]
1173
+ });
1174
+ }
1175
+ function qe({ values: e }) {
1176
+ let t = "Complete the required fields to preview this rate.";
1177
+ try {
1178
+ let n = ke(e);
1179
+ t = Ie({ price: n.price }), n.allowance?.included !== void 0 && (t += ` · ${n.allowance.included.toLocaleString()} included`);
1180
+ } catch {}
1181
+ return /* @__PURE__ */ F("section", {
1182
+ className: "rounded-lg bg-muted/50 px-3 py-2.5",
1183
+ "aria-live": "polite",
1184
+ children: [/* @__PURE__ */ P("p", {
1185
+ className: "text-xs font-medium text-muted-foreground",
1186
+ children: /* @__PURE__ */ P(o, { id: "Rate preview" })
1187
+ }), /* @__PURE__ */ P("p", {
1188
+ className: "mt-1 text-sm font-medium tabular-nums",
1189
+ children: t
1190
+ })]
1191
+ });
1192
+ }
1193
+ function K({ id: t, label: n, value: r, onChange: i, placeholder: a, inputMode: o }) {
1194
+ let { id: s } = e(), l = Je(t);
1195
+ return /* @__PURE__ */ F("div", {
1196
+ className: "grid gap-1.5",
1197
+ children: [
1198
+ /* @__PURE__ */ P(j, {
1199
+ htmlFor: s(t),
1200
+ children: n
1201
+ }),
1202
+ /* @__PURE__ */ P(c, {
1203
+ id: s(t),
1204
+ value: r,
1205
+ onChange: (e) => i(e.target.value),
1206
+ placeholder: a,
1207
+ inputMode: o,
1208
+ autoComplete: "off",
1209
+ ...Y(t, l ? {
1210
+ fieldId: t,
1211
+ message: l
1212
+ } : null)
1213
+ }),
1214
+ /* @__PURE__ */ P(X, { fieldId: t })
1215
+ ]
1216
+ });
1217
+ }
1218
+ function q(e) {
1219
+ return /* @__PURE__ */ P(K, {
1220
+ ...e,
1221
+ inputMode: "decimal"
1222
+ });
1223
+ }
1224
+ function J({ id: t, label: n, value: r, onChange: i, placeholder: a, inputMode: o }) {
1225
+ let { id: s } = e(), l = Je(t);
1226
+ return /* @__PURE__ */ F("div", {
1227
+ className: "grid gap-1.5",
1228
+ children: [
1229
+ /* @__PURE__ */ P(j, {
1230
+ htmlFor: s(t),
1231
+ className: "text-xs text-muted-foreground sm:sr-only",
1232
+ children: n
1233
+ }),
1234
+ /* @__PURE__ */ P(c, {
1235
+ id: s(t),
1236
+ value: r,
1237
+ onChange: (e) => i(e.target.value),
1238
+ placeholder: a,
1239
+ inputMode: o,
1240
+ autoComplete: "off",
1241
+ ...Y(t, l ? {
1242
+ fieldId: t,
1243
+ message: l
1244
+ } : null)
1245
+ }),
1246
+ /* @__PURE__ */ P(X, { fieldId: t })
1247
+ ]
1248
+ });
1249
+ }
1250
+ function Je(e) {
1251
+ let t = M.useContext(G);
1252
+ return t?.fieldId === e ? t.message : void 0;
1253
+ }
1254
+ function Y(e, t) {
1255
+ let n = t?.fieldId === e;
1256
+ return {
1257
+ "aria-invalid": n || void 0,
1258
+ "aria-describedby": n ? `${e}-error` : void 0
1259
+ };
1260
+ }
1261
+ function X({ fieldId: t }) {
1262
+ let { id: n } = e(), r = Je(t);
1263
+ return r ? /* @__PURE__ */ P("p", {
1264
+ id: n(`${t}-error`),
1265
+ className: "text-xs text-destructive",
1266
+ children: r
1267
+ }) : null;
1268
+ }
1269
+ function Ye({ label: e, onClick: t, disabled: n }) {
1270
+ return /* @__PURE__ */ P(s, {
1271
+ type: "button",
1272
+ variant: "ghost",
1273
+ size: "icon",
1274
+ "aria-label": e,
1275
+ onClick: t,
1276
+ disabled: n,
1277
+ className: "self-end",
1278
+ children: /* @__PURE__ */ P(I, {
1279
+ icon: R,
1280
+ className: "size-4"
1281
+ })
1282
+ });
1283
+ }
1284
+ //#endregion
1285
+ //#region src/admin/pages/catalog/metering.tsx
1286
+ var Xe = 200;
1287
+ function Ze() {
1288
+ let { text: n } = e(), { adminQueries: i } = r(), [a, l] = M.useState(""), d = T("", Xe), { data: f, isPending: p, error: m, refetch: h } = me(i.usageMeters(d.size, d.cursor)), g = u(), _ = f?.data ?? [], v = a.trim().toLowerCase(), y = v ? _.filter((e) => [
1289
+ e.key,
1290
+ e.event_type,
1291
+ e.aggregation,
1292
+ e.unit,
1293
+ e.rate_card?.product_key
1294
+ ].some((e) => e?.toLowerCase().includes(v))) : _, b = we({
1295
+ pending: p,
1296
+ error: m instanceof t ? m : m ? { status: 500 } : null,
1297
+ count: _.length
1298
+ });
1299
+ return /* @__PURE__ */ F("div", {
1300
+ className: "flex min-w-0 flex-col gap-5",
1301
+ children: [
1302
+ /* @__PURE__ */ F("div", {
1303
+ className: "flex flex-wrap items-start justify-between gap-4",
1304
+ children: [/* @__PURE__ */ F("div", {
1305
+ className: "max-w-2xl",
1306
+ children: [/* @__PURE__ */ P("h1", {
1307
+ className: "text-2xl font-semibold tracking-tight text-balance",
1308
+ children: /* @__PURE__ */ P(o, { id: "Metering" })
1309
+ }), /* @__PURE__ */ P("p", {
1310
+ className: "mt-1 text-sm text-pretty text-muted-foreground",
1311
+ children: /* @__PURE__ */ P(o, { id: "Define usage streams and the default rates charged when usage is recorded. Applications report the events separately." })
1312
+ })]
1313
+ }), g && b !== "permission" && /* @__PURE__ */ P(Re, { writesAllowed: !0 })]
1314
+ }),
1315
+ f && !g && /* @__PURE__ */ P(Q, { children: /* @__PURE__ */ P(o, { id: "Catalog updates are disabled. Meter definitions and rates are visible here; changes require the host operator." }) }),
1316
+ b === "loading" ? /* @__PURE__ */ P(tt, {}) : b === "permission" ? /* @__PURE__ */ P($, {
1317
+ title: n("Metering access is restricted"),
1318
+ description: n("Your role does not have permission to read the merchant catalog.")
1319
+ }) : b === "error" ? /* @__PURE__ */ P($, {
1320
+ title: n("Metering could not be loaded"),
1321
+ description: n("Try again. If the problem continues, check the OpenRails API logs."),
1322
+ action: /* @__PURE__ */ P(s, {
1323
+ variant: "outline",
1324
+ size: "sm",
1325
+ onClick: () => void h(),
1326
+ children: /* @__PURE__ */ P(o, { id: "Try again" })
1327
+ })
1328
+ }) : b === "empty" ? /* @__PURE__ */ P($, {
1329
+ title: n("No usage meters yet"),
1330
+ description: n("Create a meter to describe the events your application will report and bill."),
1331
+ action: g ? /* @__PURE__ */ P(Re, { writesAllowed: !0 }) : void 0
1332
+ }) : /* @__PURE__ */ F(N, { children: [
1333
+ /* @__PURE__ */ F("div", {
1334
+ className: "relative w-full sm:max-w-xs",
1335
+ children: [/* @__PURE__ */ P(I, {
1336
+ icon: xe,
1337
+ className: "absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
1338
+ }), /* @__PURE__ */ P(c, {
1339
+ value: a,
1340
+ onChange: (e) => l(e.target.value),
1341
+ className: "pl-8",
1342
+ placeholder: n("Filter this page…"),
1343
+ "aria-label": n("Filter meters on this page")
1344
+ })]
1345
+ }),
1346
+ /* @__PURE__ */ P("div", {
1347
+ className: "max-w-full overflow-x-auto",
1348
+ children: /* @__PURE__ */ F(k, { children: [/* @__PURE__ */ P(te, { children: /* @__PURE__ */ F(O, {
1349
+ className: "hover:bg-transparent",
1350
+ children: [
1351
+ /* @__PURE__ */ P(E, {
1352
+ className: "text-muted-foreground",
1353
+ children: /* @__PURE__ */ P(o, { id: "Meter" })
1354
+ }),
1355
+ /* @__PURE__ */ P(E, {
1356
+ className: "text-muted-foreground",
1357
+ children: /* @__PURE__ */ P(o, { id: "Event" })
1358
+ }),
1359
+ /* @__PURE__ */ P(E, {
1360
+ className: "text-muted-foreground",
1361
+ children: /* @__PURE__ */ P(o, { id: "Aggregation" })
1362
+ }),
1363
+ /* @__PURE__ */ P(E, {
1364
+ className: "text-muted-foreground",
1365
+ children: /* @__PURE__ */ P(o, { id: "Default price" })
1366
+ }),
1367
+ /* @__PURE__ */ P(E, {
1368
+ className: "text-muted-foreground",
1369
+ children: /* @__PURE__ */ P(o, { id: "Product" })
1370
+ }),
1371
+ /* @__PURE__ */ P(E, {
1372
+ className: "text-muted-foreground",
1373
+ children: /* @__PURE__ */ P(o, { id: "Activity" })
1374
+ }),
1375
+ /* @__PURE__ */ P(E, {
1376
+ className: "text-muted-foreground",
1377
+ children: /* @__PURE__ */ P(o, { id: "Last event" })
1378
+ }),
1379
+ /* @__PURE__ */ P(E, { children: /* @__PURE__ */ P("span", {
1380
+ className: "sr-only",
1381
+ children: /* @__PURE__ */ P(o, { id: "Open" })
1382
+ }) })
1383
+ ]
1384
+ }) }), /* @__PURE__ */ F(ee, { children: [y.map((e) => /* @__PURE__ */ P(Qe, { meter: e }, e.key)), y.length === 0 && /* @__PURE__ */ P(O, { children: /* @__PURE__ */ F(D, {
1385
+ colSpan: 9,
1386
+ className: "h-24 text-center text-muted-foreground",
1387
+ children: [
1388
+ /* @__PURE__ */ P(o, { id: "No meters on this page match “" }),
1389
+ a,
1390
+ "”."
1391
+ ]
1392
+ }) })] })] })
1393
+ }),
1394
+ /* @__PURE__ */ P(w, {
1395
+ pages: d,
1396
+ rows: f?.data?.length ?? 0,
1397
+ nextCursor: f?.next_cursor,
1398
+ busy: p,
1399
+ sizes: [
1400
+ 100,
1401
+ 200,
1402
+ 500
1403
+ ]
1404
+ })
1405
+ ] })
1406
+ ]
1407
+ });
1408
+ }
1409
+ function Qe({ meter: e }) {
1410
+ return /* @__PURE__ */ F(ne, {
1411
+ to: `/catalog/metering/${encodeURIComponent(e.key)}`,
1412
+ children: [
1413
+ /* @__PURE__ */ F(D, { children: [/* @__PURE__ */ P(i, {
1414
+ className: "font-medium underline-offset-3 hover:underline",
1415
+ to: `/catalog/metering/${encodeURIComponent(e.key)}`,
1416
+ children: e.key
1417
+ }), e.unit && /* @__PURE__ */ P("p", {
1418
+ className: "text-xs text-muted-foreground",
1419
+ children: e.unit
1420
+ })] }),
1421
+ /* @__PURE__ */ P(D, { children: e.event_type }),
1422
+ /* @__PURE__ */ P(D, { children: /* @__PURE__ */ P(A, {
1423
+ variant: "secondary",
1424
+ children: e.aggregation
1425
+ }) }),
1426
+ /* @__PURE__ */ P(D, {
1427
+ className: "font-medium tabular-nums",
1428
+ children: Ie(e.rate_card)
1429
+ }),
1430
+ /* @__PURE__ */ P(D, { children: e.rate_card?.product_key ?? "—" }),
1431
+ /* @__PURE__ */ P(D, { children: /* @__PURE__ */ F("span", {
1432
+ className: "inline-flex items-center gap-1.5 text-sm",
1433
+ children: [/* @__PURE__ */ P("span", { className: `size-1.5 rounded-full ${e.has_activity ? "bg-settled" : "bg-muted-foreground/50"}` }), e.has_activity ? "Active" : "No events"]
1434
+ }) }),
1435
+ /* @__PURE__ */ P(D, {
1436
+ className: "text-muted-foreground tabular-nums",
1437
+ children: h(e.last_event_at)
1438
+ }),
1439
+ /* @__PURE__ */ P(D, {
1440
+ className: "text-right",
1441
+ children: /* @__PURE__ */ P(I, {
1442
+ icon: ve,
1443
+ className: "ml-auto size-4 text-muted-foreground"
1444
+ })
1445
+ })
1446
+ ]
1447
+ });
1448
+ }
1449
+ function $e() {
1450
+ let { text: i } = e(), { adminQueries: c } = r(), { key: l = "" } = n(), d = l, f = a(), p = me(c.usageMeter(d)), m = u(), h = me(c.allProducts({ errorAction: "Load products for metering" }));
1451
+ if (p.isPending) return /* @__PURE__ */ P(nt, {});
1452
+ if (p.error) {
1453
+ let e = p.error instanceof t && p.error.status === 404, n = p.error instanceof t && p.error.status === 403;
1454
+ return /* @__PURE__ */ P($, {
1455
+ title: n ? "Metering access is restricted" : e ? "Meter not found" : "Meter could not be loaded",
1456
+ description: n ? "Your role does not have permission to read this meter." : e ? "This meter does not exist in the active merchant catalog." : "Try loading the meter again.",
1457
+ action: n ? void 0 : /* @__PURE__ */ P(s, {
1458
+ variant: "outline",
1459
+ size: "sm",
1460
+ onClick: () => e ? f("/catalog/metering") : void p.refetch(),
1461
+ children: e ? "Back to metering" : "Try again"
1462
+ })
1463
+ });
1464
+ }
1465
+ let g = p.data;
1466
+ if (!g) return null;
1467
+ let _ = Le(g, m);
1468
+ return /* @__PURE__ */ F("div", {
1469
+ className: "flex min-w-0 flex-col gap-8",
1470
+ children: [
1471
+ /* @__PURE__ */ F("header", {
1472
+ className: "flex flex-wrap items-start gap-3",
1473
+ children: [
1474
+ /* @__PURE__ */ P(s, {
1475
+ variant: "ghost",
1476
+ size: "icon",
1477
+ onClick: () => f("/catalog/metering"),
1478
+ "aria-label": i("Back to metering"),
1479
+ children: /* @__PURE__ */ P(I, {
1480
+ icon: _e,
1481
+ className: "size-4"
1482
+ })
1483
+ }),
1484
+ /* @__PURE__ */ F("div", {
1485
+ className: "min-w-0 flex-1",
1486
+ children: [/* @__PURE__ */ F("div", {
1487
+ className: "flex flex-wrap items-center gap-2",
1488
+ children: [/* @__PURE__ */ P("h1", {
1489
+ className: "truncate text-xl font-semibold tracking-tight",
1490
+ children: g.key
1491
+ }), !m && /* @__PURE__ */ P(A, {
1492
+ variant: "secondary",
1493
+ children: /* @__PURE__ */ P(o, { id: "read-only" })
1494
+ })]
1495
+ }), /* @__PURE__ */ F("p", {
1496
+ className: "mt-1 text-sm text-muted-foreground",
1497
+ children: [
1498
+ g.event_type,
1499
+ " · ",
1500
+ g.aggregation,
1501
+ g.unit ? ` · ${g.unit}` : ""
1502
+ ]
1503
+ })]
1504
+ }),
1505
+ /* @__PURE__ */ F("div", {
1506
+ className: "flex flex-wrap gap-2",
1507
+ children: [/* @__PURE__ */ P(Re, {
1508
+ meter: g,
1509
+ writesAllowed: m
1510
+ }), /* @__PURE__ */ P(ze, {
1511
+ meter: g,
1512
+ writesAllowed: m,
1513
+ products: h.data?.data ?? [],
1514
+ productsPending: h.isPending,
1515
+ productsError: !!h.error,
1516
+ productsForbidden: h.error instanceof t && h.error.status === 403
1517
+ })]
1518
+ })
1519
+ ]
1520
+ }),
1521
+ !m && /* @__PURE__ */ P(Q, { children: /* @__PURE__ */ P(o, { id: "Catalog updates are disabled. The console is read-only." }) }),
1522
+ /* @__PURE__ */ F("section", {
1523
+ className: "grid gap-4",
1524
+ children: [
1525
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("h2", {
1526
+ className: "text-base font-semibold",
1527
+ children: /* @__PURE__ */ P(o, { id: "Event contract" })
1528
+ }), /* @__PURE__ */ F("p", {
1529
+ className: "mt-1 max-w-3xl text-sm text-pretty text-muted-foreground",
1530
+ children: [
1531
+ /* @__PURE__ */ P(o, { id: "Creating this meter does not send events. The host application must report idempotent usage to" }),
1532
+ " ",
1533
+ /* @__PURE__ */ P("code", {
1534
+ className: "text-foreground",
1535
+ children: /* @__PURE__ */ P(o, { id: "/app/usage-events" })
1536
+ }),
1537
+ /* @__PURE__ */ P(o, { id: " with this shape." })
1538
+ ]
1539
+ })] }),
1540
+ /* @__PURE__ */ F("dl", {
1541
+ className: "grid gap-x-8 gap-y-4 border-y py-4 sm:grid-cols-2 lg:grid-cols-4",
1542
+ children: [
1543
+ /* @__PURE__ */ P(Z, {
1544
+ label: i("Event type"),
1545
+ value: g.event_type
1546
+ }),
1547
+ /* @__PURE__ */ P(Z, {
1548
+ label: i("Aggregation"),
1549
+ value: g.aggregation === "sum" ? `Sum ${g.value_property}` : "Count each event"
1550
+ }),
1551
+ /* @__PURE__ */ P(Z, {
1552
+ label: i("Meter key"),
1553
+ value: g.key
1554
+ }),
1555
+ /* @__PURE__ */ P(Z, {
1556
+ label: i("Billing support"),
1557
+ value: g.billing_supported ? "Supported" : "Read only"
1558
+ }),
1559
+ Object.entries(g.group_by ?? {}).map(([e, t]) => /* @__PURE__ */ P(Z, {
1560
+ label: `Dimension: ${e}`,
1561
+ value: t
1562
+ }, e))
1563
+ ]
1564
+ }),
1565
+ _ && m && /* @__PURE__ */ F("p", {
1566
+ className: "flex items-center gap-2 text-xs text-muted-foreground",
1567
+ children: [/* @__PURE__ */ P(I, {
1568
+ icon: ge,
1569
+ className: "size-4"
1570
+ }), _]
1571
+ })
1572
+ ]
1573
+ }),
1574
+ /* @__PURE__ */ P(et, {
1575
+ meter: g,
1576
+ writesAllowed: m
1577
+ })
1578
+ ]
1579
+ });
1580
+ }
1581
+ function et({ meter: t, writesAllowed: n }) {
1582
+ let { toast: i, toastApiError: a, adminMutations: c } = r(), { text: l } = e(), u = _(), d = he(), f = pe(c.deleteDefaultUsageRateCard(d)), p = t.rate_card, m = async () => {
1583
+ if (await u({
1584
+ title: "Remove the default rate?",
1585
+ description: "New usage for this meter will stop being rated after removal. Billed usage orders and accrued amounts remain unchanged.",
1586
+ confirmLabel: "Remove default",
1587
+ cancelLabel: "Keep rate",
1588
+ tone: "destructive"
1589
+ })) try {
1590
+ await f.mutateAsync(t), i.success("Default rate removed");
1591
+ } catch (e) {
1592
+ a(e, "Remove default rate");
1593
+ }
1594
+ };
1595
+ return /* @__PURE__ */ F("section", {
1596
+ className: "grid gap-4 border-t pt-7",
1597
+ children: [/* @__PURE__ */ F("div", {
1598
+ className: "flex flex-wrap items-start justify-between gap-4",
1599
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("h2", {
1600
+ className: "text-base font-semibold",
1601
+ children: /* @__PURE__ */ P(o, { id: "Default rate" })
1602
+ }), /* @__PURE__ */ P("p", {
1603
+ className: "mt-1 text-sm text-muted-foreground",
1604
+ children: /* @__PURE__ */ P(o, { id: "Used for every customer." })
1605
+ })] }), p && n && /* @__PURE__ */ F(s, {
1606
+ variant: "outline",
1607
+ size: "sm",
1608
+ disabled: f.isPending,
1609
+ onClick: () => void m(),
1610
+ children: [/* @__PURE__ */ P(I, {
1611
+ icon: R,
1612
+ className: "size-4"
1613
+ }), f.isPending ? "Removing…" : "Remove default"]
1614
+ })]
1615
+ }), t.billing_supported ? p ? /* @__PURE__ */ F("dl", {
1616
+ className: "grid gap-x-8 gap-y-4 border-y py-4 sm:grid-cols-2 lg:grid-cols-4",
1617
+ children: [
1618
+ /* @__PURE__ */ P(Z, {
1619
+ label: l("Price"),
1620
+ value: Ie(p)
1621
+ }),
1622
+ /* @__PURE__ */ P(Z, {
1623
+ label: l("Product"),
1624
+ value: p.product_key
1625
+ }),
1626
+ /* @__PURE__ */ P(Z, {
1627
+ label: l("Model"),
1628
+ value: p.price.model.replace("_", " ")
1629
+ }),
1630
+ /* @__PURE__ */ P(Z, {
1631
+ label: l("Filter"),
1632
+ value: Object.keys(p.filter ?? {}).length ? Object.entries(p.filter ?? {}).map(([e, t]) => `${e}: ${t.join(", ")}`).join(" · ") : "All matching events"
1633
+ }),
1634
+ /* @__PURE__ */ P(Z, {
1635
+ label: l("Allowance"),
1636
+ value: p.allowance?.included === void 0 ? "None" : `${p.allowance.included.toLocaleString()} included`
1637
+ }),
1638
+ /* @__PURE__ */ P(Z, {
1639
+ label: l("Updated"),
1640
+ value: h(p.updated_at)
1641
+ })
1642
+ ]
1643
+ }) : /* @__PURE__ */ P("p", {
1644
+ className: "border-y py-6 text-sm text-muted-foreground",
1645
+ children: /* @__PURE__ */ P(o, { id: "No default rate. Usage is recorded but is not billed by this meter." })
1646
+ }) : /* @__PURE__ */ P(Q, { children: /* @__PURE__ */ P(o, { id: "This meter uses an aggregation that the billing engine cannot rate." }) })]
1647
+ });
1648
+ }
1649
+ function Z({ label: e, value: t }) {
1650
+ return /* @__PURE__ */ F("div", {
1651
+ className: "min-w-0",
1652
+ children: [/* @__PURE__ */ P("dt", {
1653
+ className: "text-xs text-muted-foreground",
1654
+ children: e
1655
+ }), /* @__PURE__ */ P("dd", {
1656
+ className: "mt-1 text-sm font-medium break-words tabular-nums",
1657
+ children: t || "—"
1658
+ })]
1659
+ });
1660
+ }
1661
+ function Q({ children: e }) {
1662
+ return /* @__PURE__ */ F("div", {
1663
+ className: "flex items-start gap-2 rounded-lg bg-muted/50 px-3 py-2.5 text-sm text-muted-foreground",
1664
+ children: [/* @__PURE__ */ P(I, {
1665
+ icon: ye,
1666
+ className: "mt-0.5 size-4 shrink-0"
1667
+ }), /* @__PURE__ */ P("p", { children: e })]
1668
+ });
1669
+ }
1670
+ function $({ title: e, description: t, action: n }) {
1671
+ return /* @__PURE__ */ F("div", {
1672
+ className: "flex flex-col items-start gap-3 border-y py-10",
1673
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("h2", {
1674
+ className: "text-sm font-medium",
1675
+ children: e
1676
+ }), /* @__PURE__ */ P("p", {
1677
+ className: "mt-1 text-sm text-muted-foreground",
1678
+ children: t
1679
+ })] }), n]
1680
+ });
1681
+ }
1682
+ function tt() {
1683
+ return /* @__PURE__ */ F("div", {
1684
+ className: "grid gap-3",
1685
+ children: [/* @__PURE__ */ P(l, { className: "h-8 w-64" }), Array.from({ length: 5 }).map((e, t) => /* @__PURE__ */ P(l, { className: "h-11 w-full" }, t))]
1686
+ });
1687
+ }
1688
+ function nt() {
1689
+ return /* @__PURE__ */ F("div", {
1690
+ className: "grid gap-6",
1691
+ children: [
1692
+ /* @__PURE__ */ P(l, { className: "h-10 w-72" }),
1693
+ /* @__PURE__ */ P(l, { className: "h-28 w-full" }),
1694
+ /* @__PURE__ */ P(l, { className: "h-36 w-full" }),
1695
+ /* @__PURE__ */ P(l, { className: "h-40 w-full" })
1696
+ ]
1697
+ });
1698
+ }
1699
+ //#endregion
1700
+ export { Ze as CatalogMeteringPage, $e as MeterDetailPage };
1701
+
1702
+ //# sourceMappingURL=admin-metering-BGAXbT23.js.map