@btndprojects/loam-ui-native 0.2.1 → 0.3.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 (365) hide show
  1. package/dist/accordion/index.js +4 -2
  2. package/dist/adaptive/index.js +12 -2
  3. package/dist/address-block/index.js +23 -0
  4. package/dist/alert/index.js +5 -2
  5. package/dist/analyzer/index.js +13 -5
  6. package/dist/announcement/index.js +15 -5
  7. package/dist/appearance-picker/index.js +15 -0
  8. package/dist/audio-player/index.js +26 -2
  9. package/dist/avatar/index.js +2 -2
  10. package/dist/avatar-group/index.js +5 -3
  11. package/dist/badge/index.js +6 -3
  12. package/dist/banner/index.js +3 -2
  13. package/dist/board/index.js +13 -6
  14. package/dist/button/index.js +6 -3
  15. package/dist/camera-permission/index.js +19 -11
  16. package/dist/capture-result/index.js +26 -16
  17. package/dist/card/index.js +7 -3
  18. package/dist/card-form/index.js +15 -9
  19. package/dist/carousel/index.js +3 -1
  20. package/dist/chart/index.js +15 -5
  21. package/dist/charts/index.js +18 -5
  22. package/dist/chat/index.js +35 -10
  23. package/dist/checkbox/index.js +6 -4
  24. package/dist/checklist/index.js +16 -7
  25. package/dist/checkout/index.js +25 -12
  26. package/dist/chip/index.js +7 -4
  27. package/dist/chunk-2BZD3NAP.js +1110 -0
  28. package/dist/chunk-2YKVID2V.js +35 -0
  29. package/dist/{chunk-H7DWSL4O.js → chunk-36DA3IPO.js} +115 -27
  30. package/dist/chunk-3A56MIAN.js +599 -0
  31. package/dist/{chunk-AEB7KCHQ.js → chunk-3SCKCWF5.js} +39 -28
  32. package/dist/chunk-3TZNDHKO.js +187 -0
  33. package/dist/chunk-43K3BLXV.js +9 -0
  34. package/dist/chunk-46ZJIQ2Z.js +208 -0
  35. package/dist/{chunk-PMMTGBBS.js → chunk-4CZMQDQL.js} +75 -22
  36. package/dist/chunk-4QCR3K2J.js +1 -0
  37. package/dist/{chunk-E2E3I5W2.js → chunk-5DTKORLI.js} +54 -45
  38. package/dist/{chunk-5VFZRGVD.js → chunk-5J4WFXFA.js} +32 -15
  39. package/dist/{chunk-JBMLWFSJ.js → chunk-5KJ7TEQ6.js} +83 -48
  40. package/dist/chunk-5NU33TXK.js +529 -0
  41. package/dist/chunk-6KSUS7DF.js +690 -0
  42. package/dist/{chunk-3WEZCGHX.js → chunk-6RV6UW2J.js} +140 -56
  43. package/dist/chunk-6RZM7RP2.js +520 -0
  44. package/dist/{chunk-JJLPBRVZ.js → chunk-75BDCC7K.js} +2 -0
  45. package/dist/{chunk-U5NLHYV6.js → chunk-7CGJBQUA.js} +333 -22
  46. package/dist/{chunk-I4FHVKEC.js → chunk-7IVF6JLJ.js} +16 -5
  47. package/dist/chunk-7IWCGXYA.js +143 -0
  48. package/dist/chunk-7LM4ASFH.js +172 -0
  49. package/dist/chunk-7MCEJFWV.js +341 -0
  50. package/dist/{chunk-2SY63FCH.js → chunk-7NGMUVNU.js} +66 -30
  51. package/dist/chunk-7PBSIXT7.js +355 -0
  52. package/dist/chunk-7QOYGENL.js +443 -0
  53. package/dist/{chunk-TDMG26JI.js → chunk-A7SWYDE5.js} +40 -9
  54. package/dist/chunk-ADHPJALR.js +3051 -0
  55. package/dist/{chunk-ZLTO5VQI.js → chunk-ALJYZLNQ.js} +131 -61
  56. package/dist/{chunk-GDKVKNR2.js → chunk-AQ5FIG74.js} +110 -30
  57. package/dist/chunk-B2MMZZQB.js +426 -0
  58. package/dist/{chunk-QYPE5JX3.js → chunk-B7JZ3N5G.js} +142 -105
  59. package/dist/{chunk-QHTVYA65.js → chunk-BL37SW6G.js} +388 -102
  60. package/dist/chunk-BTRMA7GC.js +21 -0
  61. package/dist/{chunk-FUMHAAF3.js → chunk-C7IUWIUZ.js} +243 -92
  62. package/dist/chunk-CA3DUVYD.js +10 -0
  63. package/dist/{chunk-FYWNRX4F.js → chunk-CBCJSO2B.js} +143 -13
  64. package/dist/chunk-CHPX4MFI.js +239 -0
  65. package/dist/chunk-CLGAMIOT.js +648 -0
  66. package/dist/chunk-CUE7VML6.js +1141 -0
  67. package/dist/{chunk-D5N5QWI7.js → chunk-CVU6S2E5.js} +497 -235
  68. package/dist/{chunk-U23FYWME.js → chunk-CXPQMA6Z.js} +101 -34
  69. package/dist/{chunk-36EC2T6P.js → chunk-D2LN4I7I.js} +1 -1
  70. package/dist/{chunk-TLCIR6RG.js → chunk-D34LNBO5.js} +411 -155
  71. package/dist/{chunk-FV6HMP7W.js → chunk-D4BCQICM.js} +207 -65
  72. package/dist/chunk-EABKIIA4.js +1 -0
  73. package/dist/chunk-EICSYRAG.js +341 -0
  74. package/dist/chunk-EMWAJMAS.js +83 -0
  75. package/dist/chunk-EOLZWRV6.js +149 -0
  76. package/dist/chunk-EOQVTGB6.js +350 -0
  77. package/dist/{chunk-ZVATDZOM.js → chunk-ESGUHNB2.js} +106 -28
  78. package/dist/{chunk-46MMSDGL.js → chunk-F2KNBPKY.js} +104 -73
  79. package/dist/{chunk-KQZ3GLHR.js → chunk-G7H3NX3G.js} +40 -17
  80. package/dist/{chunk-3QMEOFW5.js → chunk-GM7YIPB7.js} +421 -207
  81. package/dist/{chunk-QHAITQIF.js → chunk-GVQQG435.js} +256 -86
  82. package/dist/chunk-HE43OMEL.js +1056 -0
  83. package/dist/{chunk-XIDTBCBA.js → chunk-HHOMFQ7R.js} +1049 -207
  84. package/dist/chunk-HNAKS4Z3.js +207 -0
  85. package/dist/chunk-HP6ST2OW.js +352 -0
  86. package/dist/chunk-HW3OWDTU.js +1 -0
  87. package/dist/{chunk-QP3KMOVF.js → chunk-HZDB44K4.js} +24 -14
  88. package/dist/chunk-I6CUP2LW.js +1155 -0
  89. package/dist/chunk-ICV4Y2WY.js +27 -0
  90. package/dist/chunk-IHSIENOE.js +3950 -0
  91. package/dist/{chunk-T5LTPKX6.js → chunk-IMMALLRU.js} +53 -25
  92. package/dist/{chunk-C4GTDLRC.js → chunk-JA6TK7H2.js} +154 -67
  93. package/dist/{chunk-EVOIGUBI.js → chunk-JAVZ5JPV.js} +43 -13
  94. package/dist/{chunk-CPTOADB2.js → chunk-JCMTP3E4.js} +527 -201
  95. package/dist/{chunk-OJQUBQWA.js → chunk-JCXFFK64.js} +73 -16
  96. package/dist/{chunk-V2OEB75Z.js → chunk-JWCVBFDU.js} +75 -35
  97. package/dist/chunk-JXRTD5RI.js +414 -0
  98. package/dist/chunk-JYIUZUIQ.js +1567 -0
  99. package/dist/chunk-K3TK3GIV.js +219 -0
  100. package/dist/chunk-KEVZIHM2.js +1511 -0
  101. package/dist/{chunk-VAOAKWUK.js → chunk-KHZDNQQD.js} +42 -8
  102. package/dist/chunk-KL4GDV4V.js +131 -0
  103. package/dist/{chunk-Q6NKEPRE.js → chunk-KNILMM4H.js} +73 -28
  104. package/dist/chunk-KRBUZV45.js +25 -0
  105. package/dist/{chunk-7BUIKDD6.js → chunk-KXLDK6HB.js} +91 -30
  106. package/dist/chunk-KZ3X7TSL.js +196 -0
  107. package/dist/{chunk-5UTRIXQ6.js → chunk-L2WMOA2V.js} +187 -43
  108. package/dist/chunk-L4D5LHCH.js +109 -0
  109. package/dist/{chunk-W63AJTM7.js → chunk-LAUJPLDB.js} +236 -71
  110. package/dist/{chunk-TN2ZNJUI.js → chunk-LGNTP5XA.js} +47 -13
  111. package/dist/chunk-LUZFCCSD.js +271 -0
  112. package/dist/{chunk-XTORZWRF.js → chunk-LXJCP4PL.js} +111 -30
  113. package/dist/chunk-MCOZJWPU.js +731 -0
  114. package/dist/{chunk-SATMR6SG.js → chunk-MG4SKWLL.js} +780 -142
  115. package/dist/{chunk-JUYWSSKW.js → chunk-MPEPTSER.js} +95 -16
  116. package/dist/chunk-MWPJ4YGP.js +1 -0
  117. package/dist/{chunk-LUMVGO2K.js → chunk-N7AX4OA4.js} +80 -29
  118. package/dist/chunk-NHSLM6SE.js +523 -0
  119. package/dist/{chunk-IT6FUXXG.js → chunk-NNJLVA7M.js} +43 -11
  120. package/dist/{chunk-TQVAIKFD.js → chunk-NZG75DGA.js} +102 -62
  121. package/dist/chunk-O76QXRBV.js +431 -0
  122. package/dist/chunk-OANH27AK.js +223 -0
  123. package/dist/chunk-OCHPK5YV.js +609 -0
  124. package/dist/chunk-OMHVEVX4.js +436 -0
  125. package/dist/{chunk-SWS5JQIF.js → chunk-ONKQUJWD.js} +187 -60
  126. package/dist/chunk-OVTK7A6T.js +615 -0
  127. package/dist/{chunk-UXGIW7OK.js → chunk-PCEFCOLN.js} +5 -1
  128. package/dist/{chunk-QIKT7LIB.js → chunk-PFLNFIVB.js} +91 -23
  129. package/dist/chunk-PHSZY37H.js +300 -0
  130. package/dist/chunk-PJLTKDVY.js +18 -0
  131. package/dist/{chunk-SHHY5OMK.js → chunk-PK7BN3MI.js} +83 -15
  132. package/dist/{chunk-YXOAPXMU.js → chunk-PWFRDRGS.js} +101 -14
  133. package/dist/{chunk-TY4MTKQJ.js → chunk-PYPMD46W.js} +332 -66
  134. package/dist/chunk-Q6CCHDI7.js +331 -0
  135. package/dist/chunk-QFA5WS2A.js +750 -0
  136. package/dist/chunk-QJMMM4RC.js +124 -0
  137. package/dist/chunk-QYWEVAM6.js +407 -0
  138. package/dist/chunk-R5T4VZ7Z.js +126 -0
  139. package/dist/chunk-R77HFLZD.js +1 -0
  140. package/dist/{chunk-LMPHCVJJ.js → chunk-RAESDNU5.js} +162 -68
  141. package/dist/chunk-RBYQUXNL.js +1 -0
  142. package/dist/chunk-RCM3DT5E.js +1 -0
  143. package/dist/chunk-RGNY56L7.js +282 -0
  144. package/dist/chunk-RIK6UX2K.js +344 -0
  145. package/dist/{chunk-5LAAAXFP.js → chunk-RJA3RXO3.js} +63 -54
  146. package/dist/chunk-RJYRJ3LD.js +1 -0
  147. package/dist/chunk-RMA3NOY4.js +599 -0
  148. package/dist/{chunk-VDPK5CY4.js → chunk-RSWKKAHK.js} +143 -61
  149. package/dist/{chunk-B7N4ASYE.js → chunk-RVOIIX3V.js} +17 -45
  150. package/dist/chunk-SA2RRBGT.js +1077 -0
  151. package/dist/{chunk-7OVVSVEZ.js → chunk-SG3J4R45.js} +440 -169
  152. package/dist/chunk-SPUK7JD4.js +238 -0
  153. package/dist/chunk-SWXV2K5N.js +434 -0
  154. package/dist/chunk-SYJEPXP6.js +1303 -0
  155. package/dist/{chunk-LKFC4CS7.js → chunk-SZLI34TA.js} +18 -9
  156. package/dist/{chunk-NBEF4EPJ.js → chunk-T77WJA74.js} +131 -16
  157. package/dist/chunk-TDWWVJA4.js +630 -0
  158. package/dist/chunk-TFHI5XDR.js +610 -0
  159. package/dist/chunk-TH4PW2WU.js +17 -0
  160. package/dist/chunk-TTQ24HQX.js +12 -0
  161. package/dist/chunk-TUACVJNG.js +12 -0
  162. package/dist/{chunk-F5B3UINI.js → chunk-TUL5RUIA.js} +171 -62
  163. package/dist/{chunk-C6APNDVA.js → chunk-TYOSA7JG.js} +63 -34
  164. package/dist/chunk-TYQTMMEV.js +1 -0
  165. package/dist/{chunk-DW3L54DQ.js → chunk-TZO6YDS7.js} +53 -12
  166. package/dist/{chunk-67IZZ2MJ.js → chunk-U3ETF22F.js} +75 -30
  167. package/dist/{chunk-EDCBJV7J.js → chunk-U6BYHD2N.js} +87 -31
  168. package/dist/{chunk-ENP3BMZU.js → chunk-UF6EJXPQ.js} +16 -1
  169. package/dist/{chunk-IPUNJMAQ.js → chunk-UNNQIPGK.js} +304 -68
  170. package/dist/chunk-UQVO6AJV.js +171 -0
  171. package/dist/{chunk-FZGAAOKS.js → chunk-VFDQAAIW.js} +138 -32
  172. package/dist/chunk-VIUE3VQT.js +1 -0
  173. package/dist/{chunk-5RENVKBQ.js → chunk-VJLSSSGC.js} +126 -30
  174. package/dist/chunk-VLMT6KYT.js +350 -0
  175. package/dist/chunk-VMHGBUGS.js +35 -0
  176. package/dist/{chunk-4IZXHVFJ.js → chunk-VQKPBYW6.js} +228 -172
  177. package/dist/{chunk-G6UESEVN.js → chunk-VSSTWLC5.js} +49 -11
  178. package/dist/{chunk-TRGFFU6A.js → chunk-VZYYZRPN.js} +866 -330
  179. package/dist/{chunk-JLC6PM5S.js → chunk-WAIJCD2V.js} +128 -54
  180. package/dist/chunk-WFMQ3WKM.js +378 -0
  181. package/dist/chunk-WJ2KDRMY.js +66 -0
  182. package/dist/chunk-WKFZJO54.js +437 -0
  183. package/dist/{chunk-QEYFDRHR.js → chunk-WVVD3XOV.js} +146 -84
  184. package/dist/chunk-XAIWMSLB.js +1 -0
  185. package/dist/chunk-XBXUBBJZ.js +98 -0
  186. package/dist/chunk-XCU7MYBJ.js +1 -0
  187. package/dist/chunk-XHE4PGCI.js +717 -0
  188. package/dist/chunk-XRSJ32M3.js +331 -0
  189. package/dist/chunk-XTCVOEAW.js +1 -0
  190. package/dist/chunk-XWGXVQF6.js +58 -0
  191. package/dist/{chunk-MKSNFG7H.js → chunk-Y3XKKO5K.js} +191 -109
  192. package/dist/chunk-Y4QNMBLO.js +533 -0
  193. package/dist/chunk-Y5H4CTKO.js +1 -0
  194. package/dist/chunk-YBQIN75A.js +403 -0
  195. package/dist/{chunk-PNF3NKB5.js → chunk-YJ5PXOX3.js} +28 -11
  196. package/dist/{chunk-M656FYNH.js → chunk-YLRSRUPS.js} +63 -49
  197. package/dist/chunk-YM6MPJ4A.js +1 -0
  198. package/dist/chunk-YV7KZENV.js +200 -0
  199. package/dist/chunk-Z7I4ZSO6.js +316 -0
  200. package/dist/{chunk-EY4DD67D.js → chunk-ZIRMWD2B.js} +199 -126
  201. package/dist/chunk-ZPMG3FWU.js +75 -0
  202. package/dist/{chunk-QRUMA22E.js → chunk-ZTXMK2G7.js} +92 -43
  203. package/dist/{chunk-2OLKPG4E.js → chunk-ZVJCWXAL.js} +189 -87
  204. package/dist/{chunk-YAAHPATV.js → chunk-ZYQ23DPT.js} +49 -34
  205. package/dist/coachmark/index.js +7 -3
  206. package/dist/code-block/index.js +4 -3
  207. package/dist/color-field/index.js +12 -4
  208. package/dist/color-picker/index.js +23 -0
  209. package/dist/commerce/index.js +27 -16
  210. package/dist/confirm/index.js +31 -0
  211. package/dist/connection-card/index.js +34 -0
  212. package/dist/connectivity/index.js +3 -2
  213. package/dist/context-menu/index.js +10 -2
  214. package/dist/copy-button/index.js +3 -2
  215. package/dist/data-grid/index.js +30 -17
  216. package/dist/date-range-picker/index.js +19 -9
  217. package/dist/description-list/index.js +4 -1
  218. package/dist/device-frame/index.js +30 -0
  219. package/dist/dialog/index.js +8 -2
  220. package/dist/divider/index.js +2 -0
  221. package/dist/empty-state/index.js +13 -2
  222. package/dist/error-summary/index.js +7 -2
  223. package/dist/fab/index.js +4 -2
  224. package/dist/file-manager/index.js +33 -17
  225. package/dist/file-upload/index.js +12 -6
  226. package/dist/filter-bar/index.js +10 -6
  227. package/dist/flow-run/index.js +19 -12
  228. package/dist/form/index.js +30 -3
  229. package/dist/gallery/index.js +5 -2
  230. package/dist/hold-to-confirm/index.js +4 -2
  231. package/dist/hover-card/index.js +18 -0
  232. package/dist/icon-tile/index.js +10 -0
  233. package/dist/image/index.js +9 -0
  234. package/dist/index.d.ts +29826 -17941
  235. package/dist/index.js +197 -141
  236. package/dist/infinite-list/index.js +4 -2
  237. package/dist/inline-edit/index.js +5 -4
  238. package/dist/input/index.js +4 -3
  239. package/dist/interactions/index.js +4 -1
  240. package/dist/invoice/index.js +18 -9
  241. package/dist/job-row/index.js +22 -0
  242. package/dist/json-inspector/index.js +20 -0
  243. package/dist/kbd/index.js +2 -2
  244. package/dist/keyboard/index.js +7 -2
  245. package/dist/level-meter/index.js +9 -0
  246. package/dist/list-row/index.js +11 -3
  247. package/dist/log-viewer/index.js +9 -2
  248. package/dist/map-view/index.js +13 -2
  249. package/dist/markdown/index.js +8 -5
  250. package/dist/metric/index.js +6 -3
  251. package/dist/metric-strip/index.js +12 -0
  252. package/dist/money/index.js +11 -4
  253. package/dist/nav-drawer/index.js +6 -2
  254. package/dist/nav-header/index.js +10 -4
  255. package/dist/navigation/index.js +29 -2
  256. package/dist/notification-center/index.js +24 -10
  257. package/dist/number-roll/index.js +3 -1
  258. package/dist/onboarding-pager/index.js +22 -0
  259. package/dist/one-handed/index.js +2 -2
  260. package/dist/os-surfaces/index.js +6 -3
  261. package/dist/otp/index.js +5 -4
  262. package/dist/page-header/index.js +2 -1
  263. package/dist/pagination/index.js +4 -2
  264. package/dist/payment-method/index.js +17 -11
  265. package/dist/payment-status/index.js +22 -14
  266. package/dist/permission/index.js +18 -2
  267. package/dist/picker/index.js +17 -6
  268. package/dist/progress/index.js +7 -2
  269. package/dist/provenance/index.js +16 -0
  270. package/dist/pull-to-refresh/index.js +2 -2
  271. package/dist/qr-code/index.js +16 -0
  272. package/dist/query-builder/index.js +30 -0
  273. package/dist/radio-group/index.js +6 -4
  274. package/dist/rating/index.js +7 -2
  275. package/dist/receivables/index.js +31 -18
  276. package/dist/recording-indicator/index.js +21 -0
  277. package/dist/refund/index.js +24 -15
  278. package/dist/repeatable-rows/index.js +19 -0
  279. package/dist/save-status/index.js +5 -3
  280. package/dist/screen/index.js +3 -0
  281. package/dist/scroll-area/index.js +1 -1
  282. package/dist/search-field/index.js +8 -3
  283. package/dist/secret-field/index.js +19 -0
  284. package/dist/section-header/index.js +4 -0
  285. package/dist/segmented-control/index.js +2 -2
  286. package/dist/sheet/index.js +9 -3
  287. package/dist/shortcuts-sheet/index.js +2 -0
  288. package/dist/sign-in-screen/index.js +25 -0
  289. package/dist/skeleton/index.js +3 -1
  290. package/dist/slider/index.js +2 -1
  291. package/dist/sortable/index.js +4 -3
  292. package/dist/spinner/index.js +2 -1
  293. package/dist/split-button/index.js +17 -5
  294. package/dist/spotlight/index.js +7 -1
  295. package/dist/stack/index.js +2 -0
  296. package/dist/stage-timeline/index.js +6 -3
  297. package/dist/status-dot/index.js +6 -2
  298. package/dist/stepper/index.js +7 -3
  299. package/dist/streaming-text/index.js +2 -1
  300. package/dist/survey/index.js +24 -14
  301. package/dist/switch/index.js +6 -2
  302. package/dist/system-state/index.js +12 -4
  303. package/dist/tab-bar/index.js +10 -2
  304. package/dist/tabs/index.js +10 -2
  305. package/dist/tags-input/index.js +8 -5
  306. package/dist/text/index.js +4 -0
  307. package/dist/textarea/index.js +5 -4
  308. package/dist/thinking/index.js +4 -1
  309. package/dist/tile-rail/index.js +10 -0
  310. package/dist/time-field/index.js +15 -7
  311. package/dist/time-range-control/index.js +26 -12
  312. package/dist/timeline/index.js +2 -2
  313. package/dist/toast/index.js +4 -2
  314. package/dist/toolbar/index.js +3 -2
  315. package/dist/tour/index.js +12 -10
  316. package/dist/transcript/index.js +28 -0
  317. package/dist/truncation-notice/index.js +2 -2
  318. package/dist/update-notice/index.js +15 -8
  319. package/dist/video-player/index.js +26 -2
  320. package/dist/viewfinder/index.js +12 -4
  321. package/dist/widget/index.js +11 -4
  322. package/dist/wizard/index.js +7 -4
  323. package/package.json +13 -13
  324. package/dist/chunk-2PKYGLQ6.js +0 -268
  325. package/dist/chunk-2SWKL3AJ.js +0 -466
  326. package/dist/chunk-2TXERVVA.js +0 -1081
  327. package/dist/chunk-3DUWIYV5.js +0 -437
  328. package/dist/chunk-3NMD74ZU.js +0 -4
  329. package/dist/chunk-4DS5ZWVC.js +0 -83
  330. package/dist/chunk-6YAQBXB3.js +0 -93
  331. package/dist/chunk-74FLKD24.js +0 -237
  332. package/dist/chunk-CMTVNF3D.js +0 -104
  333. package/dist/chunk-DN7MNQIP.js +0 -799
  334. package/dist/chunk-DVGBZ3TX.js +0 -455
  335. package/dist/chunk-F3H33DQX.js +0 -300
  336. package/dist/chunk-FAJI7BSC.js +0 -443
  337. package/dist/chunk-G3AFC24V.js +0 -60
  338. package/dist/chunk-HJLPZA4X.js +0 -369
  339. package/dist/chunk-HYEOQWT7.js +0 -647
  340. package/dist/chunk-IDM7JJMO.js +0 -110
  341. package/dist/chunk-IVKMZ7BB.js +0 -326
  342. package/dist/chunk-IXKWIFWZ.js +0 -334
  343. package/dist/chunk-JV5YOTOB.js +0 -164
  344. package/dist/chunk-KFJGFLMW.js +0 -158
  345. package/dist/chunk-LQP4KEXZ.js +0 -214
  346. package/dist/chunk-NTQ2F3AU.js +0 -257
  347. package/dist/chunk-O5V4TG3V.js +0 -329
  348. package/dist/chunk-OWAMM2DK.js +0 -280
  349. package/dist/chunk-PID3NJB7.js +0 -405
  350. package/dist/chunk-QDZGFXQD.js +0 -176
  351. package/dist/chunk-QPWDDJJ4.js +0 -385
  352. package/dist/chunk-ROCUG24E.js +0 -416
  353. package/dist/chunk-RU3ZPNL6.js +0 -1986
  354. package/dist/chunk-RXSCIO6W.js +0 -153
  355. package/dist/chunk-SKWO3SZF.js +0 -2284
  356. package/dist/chunk-UQGBTPXH.js +0 -218
  357. package/dist/chunk-UYGDJWMN.js +0 -273
  358. package/dist/chunk-W74TXYFB.js +0 -107
  359. package/dist/chunk-WRDSPUE7.js +0 -417
  360. package/dist/chunk-XBZGDDMR.js +0 -105
  361. package/dist/chunk-XN4KG3P4.js +0 -1040
  362. package/dist/chunk-XQXMLMH3.js +0 -211
  363. package/dist/chunk-ZECZOOSB.js +0 -245
  364. /package/dist/{chunk-VFCUIDRT.js → chunk-3BKLBYPK.js} +0 -0
  365. /package/dist/{chunk-GEIGMWNF.js → chunk-QNZII37O.js} +0 -0
@@ -1,1986 +0,0 @@
1
- import { List, ListRow } from './chunk-C4GTDLRC.js';
2
- import { Switch } from './chunk-FZGAAOKS.js';
3
- import { SegmentedControl } from './chunk-TQVAIKFD.js';
4
- import { Progress } from './chunk-5UTRIXQ6.js';
5
- import { Amount, PriceRow } from './chunk-QHAITQIF.js';
6
- import { usePayLabels } from './chunk-GEIGMWNF.js';
7
- import { TextField } from './chunk-7BUIKDD6.js';
8
- import { Badge } from './chunk-TN2ZNJUI.js';
9
- import { Button } from './chunk-E2E3I5W2.js';
10
- import { useLabels, useLoamLocale } from './chunk-APCWFOZW.js';
11
- import { Icon } from './chunk-UXGIW7OK.js';
12
- import * as React2 from 'react';
13
- import { Platform, ScrollView, Text, View, Pressable } from 'react-native';
14
- import { createStyleSheet, useStyles, useLoamTheme } from '@btndprojects/loam-theme-native';
15
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
16
- import { yearlySaving, planDelta, planCta, yearlyMonthly, money } from '@btndprojects/loam-pay';
17
-
18
- // src/commerce/commerce-labels.ts
19
- var TOGGLE_ROW_LABELS = {
20
- withDescription: (label, description) => `${label}, ${description}`
21
- };
22
- var NOTIFICATION_PREFERENCES_LABELS = {
23
- systemOn: "System notifications are on. Turn categories off here rather than muting the whole app.",
24
- systemOff: "Notifications are turned off for this app in system settings. Your choices below are kept, and take effect as soon as you turn them back on.",
25
- openSettings: "Open Settings"
26
- };
27
- var DELETE_ACCOUNT_LABELS = {
28
- title: "Delete account",
29
- whatIsDeleted: "What is deleted",
30
- whatIsKept: "What is kept, and why",
31
- deletionCompletes: (duration) => `Deletion completes ${duration}.`,
32
- typeToConfirm: (phrase) => `Type ${phrase} to confirm`,
33
- confirm: "Delete my account",
34
- busy: "Deleting\u2026",
35
- keep: "Keep my account"
36
- };
37
- var MANAGE_SUBSCRIPTION_LABELS = {
38
- statusActive: "Active",
39
- statusTrial: "Trial",
40
- statusCanceled: "Canceled",
41
- statusPastDue: "Past due",
42
- renews: "renews",
43
- renewalLine: (price, renews, date) => `${price} \xB7 ${renews} ${date}`,
44
- payment: "Payment",
45
- paymentLine: (payment, method) => `${payment} \xB7 ${method}`,
46
- cancel: "Cancel subscription"
47
- };
48
- function DeleteAccountScreen({
49
- title: titleProp,
50
- deletes,
51
- retains,
52
- duration,
53
- confirmationPhrase,
54
- confirmationLabel,
55
- confirmationValue,
56
- onConfirmationChange,
57
- confirmLabel: confirmLabelProp,
58
- onConfirm,
59
- loading = false,
60
- busyLabel: busyLabelProp,
61
- cancelLabel: cancelLabelProp,
62
- onCancel,
63
- labels: labelsProp
64
- }) {
65
- const { styles } = useStyles(sheet);
66
- const labels = useLabels("deleteAccount", DELETE_ACCOUNT_LABELS, labelsProp);
67
- const title = titleProp ?? labels.title;
68
- const confirmLabel = confirmLabelProp ?? labels.confirm;
69
- const busyLabel = busyLabelProp ?? labels.busy;
70
- const cancelLabel = cancelLabelProp ?? labels.keep;
71
- const confirmationName = confirmationLabel ?? labels.typeToConfirm(confirmationPhrase);
72
- const theme = useLoamTheme("commerce");
73
- const isControlled = confirmationValue !== void 0;
74
- const [internal, setInternal] = React2.useState("");
75
- const typed = isControlled ? confirmationValue : internal;
76
- const armed = typed.trim() === confirmationPhrase;
77
- const change = (next) => {
78
- if (!isControlled) setInternal(next);
79
- onConfirmationChange?.(next);
80
- };
81
- return /* @__PURE__ */ jsxs(ScrollView, { style: styles.screen, contentContainerStyle: styles.scroll, children: [
82
- /* @__PURE__ */ jsx(Text, { style: styles.title, children: title }),
83
- /* @__PURE__ */ jsxs(View, { style: styles.group, children: [
84
- /* @__PURE__ */ jsx(Text, { style: styles.caption, children: labels.whatIsDeleted }),
85
- deletes.map((d) => /* @__PURE__ */ jsxs(View, { style: styles.row, children: [
86
- /* @__PURE__ */ jsx(Icon, { name: "trash", size: theme.icon.sm, color: theme.color.danger }),
87
- /* @__PURE__ */ jsx(Text, { style: styles.rowLabel, children: d })
88
- ] }, d))
89
- ] }),
90
- /* @__PURE__ */ jsxs(View, { style: styles.group, children: [
91
- /* @__PURE__ */ jsx(Text, { style: styles.caption, children: labels.whatIsKept }),
92
- retains.map((r) => /* @__PURE__ */ jsxs(View, { style: styles.row, children: [
93
- /* @__PURE__ */ jsx(Icon, { name: "lock", size: theme.icon.sm, color: theme.color.text3 }),
94
- /* @__PURE__ */ jsx(Text, { style: styles.rowLabel, children: r })
95
- ] }, r))
96
- ] }),
97
- /* @__PURE__ */ jsx(View, { style: styles.duration, children: /* @__PURE__ */ jsx(Text, { style: styles.durationText, children: labels.deletionCompletes(duration) }) }),
98
- /* @__PURE__ */ jsx(
99
- TextField,
100
- {
101
- label: confirmationName,
102
- value: typed,
103
- onChangeText: change,
104
- autoCapitalize: "characters",
105
- autoCorrect: false,
106
- accessibilityLabel: confirmationName
107
- }
108
- ),
109
- /* @__PURE__ */ jsx(
110
- Pressable,
111
- {
112
- accessibilityRole: "button",
113
- accessibilityLabel: loading ? busyLabel : confirmLabel,
114
- accessibilityState: { disabled: !armed, busy: loading },
115
- disabled: !armed,
116
- onPress: armed && !loading ? onConfirm : void 0,
117
- style: ({ pressed }) => [
118
- styles.confirm,
119
- armed ? null : styles.confirmDisabled,
120
- pressed && armed ? styles.pressed : null
121
- ],
122
- children: /* @__PURE__ */ jsx(Text, { style: [styles.confirmLabel, armed ? null : styles.confirmLabelDisabled], children: loading ? busyLabel : confirmLabel })
123
- }
124
- ),
125
- /* @__PURE__ */ jsx(
126
- Pressable,
127
- {
128
- accessibilityRole: "button",
129
- accessibilityLabel: cancelLabel,
130
- onPress: onCancel,
131
- style: ({ pressed }) => [styles.cancel, pressed ? styles.pressed : null],
132
- children: /* @__PURE__ */ jsx(Text, { style: styles.cancelLabel, children: cancelLabel })
133
- }
134
- )
135
- ] });
136
- }
137
- var sheet = createStyleSheet((theme) => ({
138
- screen: { flex: 1, backgroundColor: theme.color.bg },
139
- scroll: { padding: theme.layout.screenPad, gap: theme.space.s4 },
140
- title: {
141
- fontFamily: theme.font.display,
142
- fontWeight: theme.font.displayWeight,
143
- fontSize: theme.type.title2.fontSize,
144
- lineHeight: theme.type.title2.lineHeight,
145
- letterSpacing: theme.type.title2.letterSpacing,
146
- color: theme.color.text
147
- },
148
- group: { gap: theme.space.s2 },
149
- caption: {
150
- fontFamily: theme.font.sans,
151
- fontWeight: theme.fontWeight.bold,
152
- fontSize: theme.type.caption2.fontSize,
153
- lineHeight: theme.type.caption2.lineHeight,
154
- letterSpacing: theme.type.caption2.fontSize * theme.tracking.caps,
155
- textTransform: "uppercase",
156
- color: theme.color.text3
157
- },
158
- row: { flexDirection: "row", alignItems: "flex-start", gap: theme.space.s2 },
159
- rowLabel: {
160
- flex: 1,
161
- fontFamily: theme.font.sans,
162
- fontSize: theme.type.footnote.fontSize,
163
- lineHeight: theme.type.footnote.fontSize * theme.lineHeight.normal,
164
- color: theme.color.text
165
- },
166
- duration: {
167
- padding: theme.space.s3,
168
- borderRadius: theme.radius.md,
169
- backgroundColor: theme.color.warnSoft,
170
- borderWidth: theme.borderWidth.base,
171
- borderColor: theme.edge.warn
172
- },
173
- // Text on a `-soft` tint takes the tone itself, never the on-ink.
174
- durationText: {
175
- fontFamily: theme.font.sans,
176
- fontSize: theme.type.footnote.fontSize,
177
- lineHeight: theme.type.footnote.lineHeight,
178
- color: theme.color.warnOnSoft
179
- },
180
- confirm: {
181
- minHeight: theme.tapMin,
182
- alignItems: "center",
183
- justifyContent: "center",
184
- borderRadius: theme.radius.md,
185
- backgroundColor: theme.color.danger
186
- },
187
- // Disabled is the state layer plus `disabledOpacity`, never a hand-greyed colour.
188
- confirmDisabled: { backgroundColor: theme.state.disabledFill },
189
- // Solid `danger` fill, so its measured ink — not a flat white.
190
- confirmLabel: {
191
- fontFamily: theme.font.sans,
192
- fontWeight: theme.fontWeight.bold,
193
- fontSize: theme.type.callout.fontSize,
194
- lineHeight: theme.type.callout.lineHeight,
195
- color: theme.color.dangerInk
196
- },
197
- confirmLabelDisabled: { color: theme.color.text3, opacity: theme.state.disabledOpacity },
198
- cancel: {
199
- minHeight: theme.tapMin,
200
- alignItems: "center",
201
- justifyContent: "center"
202
- },
203
- cancelLabel: {
204
- fontFamily: theme.font.sans,
205
- fontWeight: theme.fontWeight.semibold,
206
- fontSize: theme.type.subheadline.fontSize,
207
- lineHeight: theme.type.subheadline.lineHeight,
208
- color: theme.color.text2
209
- },
210
- pressed: { opacity: theme.state.pressedOpacity }
211
- }));
212
- var DEFAULT_LABELS = {
213
- platformNote: "Billed by the app store on your account. Prices come from its catalogue.",
214
- restorePurchase: "Restore purchase",
215
- close: "Close",
216
- bestValue: "Best value",
217
- planLine: (name, price, period) => `${name} \xB7 ${price} ${period}`,
218
- planSpoken: (name, price, period) => `${name} ${price} ${period}`,
219
- notNow: "Not now",
220
- restorePurchases: "Restore purchases",
221
- meterReadout: (value, max, unit) => `${value} of ${max}${unit ? ` ${unit}` : ""}`,
222
- save: "Save",
223
- perYear: "a year",
224
- samePrice: "Same price",
225
- billedYearlyTail: "billed yearly",
226
- yourPlan: "Your plan",
227
- included: "Included",
228
- notIncluded: "Not included",
229
- featureState: (state) => `${state}: `,
230
- comparisonCell: (label, included) => `${label}: ${included ? "included" : "not included"}`,
231
- billingPeriod: "Billing period",
232
- plansCompared: "Plans compared",
233
- feature: "Feature",
234
- choosePlanRow: "Choose a plan",
235
- creditedNextInvoice: "credited to your next invoice",
236
- today: "today",
237
- then: "then",
238
- cadenceFrom: (cadence, date) => `${cadence} from ${date}`,
239
- monthly: "monthly",
240
- midCycleChange: (currency) => `Mid-cycle change \xB7 ${currency}`,
241
- unusedTime: (plan, daysLeft, cycleDays) => `Unused ${plan}, ${daysLeft} of ${cycleDays} days`,
242
- sameDays: (plan, daysLeft) => `${plan} for the same ${daysLeft} days`,
243
- creditOnNextInvoice: "Credit on your next invoice",
244
- chargedToday: "Charged today",
245
- fromDate: (date, cadence) => `From ${date}, ${cadence}`,
246
- moveTo: (plan) => `Move to ${plan}`,
247
- upgrade: "upgrade",
248
- downgrade: "downgrade",
249
- planArrow: (from, to) => `${from} \u2192 ${to}`,
250
- perCycle: "per cycle",
251
- confirmChange: (way) => `Confirm ${way}`,
252
- keepCurrentPlan: "Keep current plan",
253
- subscription: "Subscription",
254
- plan: "Plan",
255
- seats: (count) => `${count} seats`,
256
- billedYearly: "Billed yearly",
257
- billedMonthly: "Billed monthly",
258
- renews: "Renews",
259
- method: "Method",
260
- trialDaysLeft: (days) => `${days} ${days === 1 ? "day" : "days"} left in your trial`,
261
- trialUsed: "Trial used",
262
- days: "days",
263
- graceTitle: "We could not charge your card",
264
- updatePaymentMethod: "Update payment method",
265
- graceSchedule: (day) => `due \xB7 day ${day} of the retry schedule`,
266
- accessEnds: (date) => `Access ends ${date}.`,
267
- cancelPlan: (plan) => `Cancel ${plan}`,
268
- staysActiveUntil: (plan, date) => React2.createElement(React2.Fragment, null, `${plan} stays active until `, date, "."),
269
- whatYouLose: (date) => `What you lose on ${date}`,
270
- whyCancelling: "Why are you cancelling?",
271
- keepMyPlan: "Keep my plan"
272
- };
273
- var INDICATOR = { ring: 20, dot: 10 };
274
- function Paywall({
275
- title,
276
- description,
277
- features = [],
278
- meter,
279
- plans,
280
- selectedPlanId,
281
- onSelectPlan,
282
- ctaLabel,
283
- onPurchase,
284
- busy = false,
285
- legalText,
286
- restoreLabel: restoreLabelProp,
287
- onRestore,
288
- footNote,
289
- links = [],
290
- onLinkPress,
291
- onClose,
292
- closeLabel: closeLabelProp,
293
- labels: labelsProp
294
- }) {
295
- const { styles } = useStyles(sheet2);
296
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
297
- const restoreLabel = restoreLabelProp ?? labels.restorePurchase;
298
- const closeLabel = closeLabelProp ?? labels.close;
299
- const theme = useLoamTheme("commerce");
300
- const fallback = plans.find((p) => p.recommended)?.id ?? plans[0]?.id;
301
- const isControlled = selectedPlanId !== void 0;
302
- const [internal, setInternal] = React2.useState(fallback);
303
- const selected = isControlled ? selectedPlanId : internal;
304
- const select = (id) => {
305
- if (!isControlled) setInternal(id);
306
- onSelectPlan?.(id);
307
- };
308
- return /* @__PURE__ */ jsxs(View, { style: styles.screen, children: [
309
- /* @__PURE__ */ jsxs(ScrollView, { contentContainerStyle: styles.scroll, children: [
310
- onClose ? /* @__PURE__ */ jsx(View, { style: styles.closeRow, children: /* @__PURE__ */ jsx(
311
- Pressable,
312
- {
313
- accessibilityRole: "button",
314
- accessibilityLabel: closeLabel,
315
- onPress: onClose,
316
- style: styles.close,
317
- children: /* @__PURE__ */ jsx(Icon, { name: "x", size: theme.icon.md, color: theme.color.text3 })
318
- }
319
- ) }) : null,
320
- /* @__PURE__ */ jsxs(View, { style: styles.intro, children: [
321
- /* @__PURE__ */ jsx(Text, { style: styles.title, children: title }),
322
- description ? /* @__PURE__ */ jsx(Text, { style: styles.description, children: description }) : null
323
- ] }),
324
- features.length > 0 ? /* @__PURE__ */ jsx(View, { style: styles.features, children: features.map((f) => (
325
- // The glyph carries the same meaning as the tint, so the list still
326
- // reads under forced colors / greyscale.
327
- /* @__PURE__ */ jsxs(View, { style: styles.featureRow, children: [
328
- /* @__PURE__ */ jsx(Icon, { name: "check", size: theme.icon.sm, color: theme.color.good }),
329
- /* @__PURE__ */ jsx(Text, { style: styles.featureLabel, children: f })
330
- ] }, f)
331
- )) }) : null,
332
- meter,
333
- /* @__PURE__ */ jsx(View, { accessibilityRole: "radiogroup", style: styles.plans, children: plans.map((plan) => {
334
- const on = plan.id === selected;
335
- return /* @__PURE__ */ jsxs(
336
- Pressable,
337
- {
338
- accessibilityRole: "radio",
339
- accessibilityLabel: labels.planSpoken(plan.name, plan.price, plan.period),
340
- accessibilityState: { checked: on, selected: on },
341
- "aria-checked": on,
342
- onPress: () => select(plan.id),
343
- style: ({ pressed }) => [
344
- styles.plan,
345
- on ? styles.planOn : null,
346
- pressed ? styles.planPressed : null
347
- ],
348
- children: [
349
- /* @__PURE__ */ jsx(View, { style: [styles.indicator, on ? styles.indicatorOn : null], children: on ? /* @__PURE__ */ jsx(View, { style: styles.indicatorDot }) : null }),
350
- /* @__PURE__ */ jsxs(View, { style: styles.planMain, children: [
351
- plan.recommended ? /* @__PURE__ */ jsx(Badge, { style: styles.rowBadge, variant: "accent", size: "sm", children: plan.recommendedLabel ?? labels.bestValue }) : null,
352
- /* @__PURE__ */ jsx(Text, { style: styles.planTitle, children: labels.planLine(plan.name, plan.price, plan.period) }),
353
- plan.note ? /* @__PURE__ */ jsx(Text, { style: styles.planNote, children: plan.note }) : null
354
- ] })
355
- ]
356
- },
357
- plan.id
358
- );
359
- }) })
360
- ] }),
361
- /* @__PURE__ */ jsxs(View, { style: styles.footer, children: [
362
- /* @__PURE__ */ jsx(
363
- Button,
364
- {
365
- fullWidth: true,
366
- size: "lg",
367
- loading: busy,
368
- onPress: selected ? () => onPurchase?.(selected) : void 0,
369
- children: ctaLabel
370
- }
371
- ),
372
- /* @__PURE__ */ jsx(Text, { style: styles.legal, children: legalText }),
373
- footNote,
374
- /* @__PURE__ */ jsxs(View, { style: styles.links, children: [
375
- /* @__PURE__ */ jsx(
376
- Pressable,
377
- {
378
- accessibilityRole: "button",
379
- accessibilityLabel: restoreLabel,
380
- onPress: onRestore,
381
- children: /* @__PURE__ */ jsx(Text, { style: styles.link, children: restoreLabel })
382
- }
383
- ),
384
- links.map((l) => /* @__PURE__ */ jsx(
385
- Pressable,
386
- {
387
- accessibilityRole: "link",
388
- accessibilityLabel: l.label,
389
- onPress: () => onLinkPress?.(l.id),
390
- children: /* @__PURE__ */ jsx(Text, { style: styles.link, children: l.label })
391
- },
392
- l.id
393
- ))
394
- ] })
395
- ] })
396
- ] });
397
- }
398
- var sheet2 = createStyleSheet((theme) => ({
399
- screen: { flex: 1, backgroundColor: theme.color.bg },
400
- scroll: { padding: theme.layout.screenPad, gap: theme.space.s4 },
401
- closeRow: { flexDirection: "row", justifyContent: "flex-end" },
402
- close: {
403
- minWidth: theme.tapMin,
404
- minHeight: theme.tapMin,
405
- alignItems: "flex-end",
406
- justifyContent: "center"
407
- },
408
- intro: { gap: theme.space.s2 },
409
- // Product name = the display face at the "Title 1" role.
410
- title: {
411
- fontFamily: theme.font.display,
412
- fontWeight: theme.font.displayWeight,
413
- fontSize: theme.type.title1.fontSize,
414
- lineHeight: theme.type.title1.lineHeight,
415
- letterSpacing: theme.type.title1.letterSpacing,
416
- color: theme.color.text
417
- },
418
- description: {
419
- fontFamily: theme.font.sans,
420
- fontSize: theme.type.subheadline.fontSize,
421
- lineHeight: theme.type.subheadline.fontSize * theme.lineHeight.relaxed,
422
- color: theme.color.text2
423
- },
424
- features: { gap: theme.space.s2 },
425
- featureRow: { flexDirection: "row", alignItems: "center", gap: theme.space.s2 },
426
- featureLabel: {
427
- flex: 1,
428
- fontFamily: theme.font.sans,
429
- fontSize: theme.type.subheadline.fontSize,
430
- lineHeight: theme.type.subheadline.lineHeight,
431
- color: theme.color.text
432
- },
433
- plans: { gap: theme.space.s2 },
434
- plan: {
435
- flexDirection: "row",
436
- alignItems: "center",
437
- gap: theme.space.s3,
438
- minHeight: theme.tapMin,
439
- padding: theme.space.s3,
440
- borderRadius: theme.radius.md,
441
- // `borderWidth.thick` is the static scale: the plan outline is part of the
442
- // drawing (it is what "selected" looks like), not resizable chrome.
443
- borderWidth: theme.borderWidth.thick,
444
- borderColor: theme.color.borderStrong,
445
- backgroundColor: "transparent"
446
- },
447
- // `focus.ringColor`, not the raw accent: this border is what marks the chosen
448
- // plan, and it is the only thing left doing that once high contrast flattens
449
- // the `accentSoft` fill to the plain surface. It is a graphical object under
450
- // SC 1.4.11 either way — see `focusRingColor()`, which is named for the focus
451
- // ring but derives the accent at exactly the 3:1 hard-edge strength any
452
- // meaning-carrying accent edge needs. Identical to the raw accent in 9 of the
453
- // 14 palette x mode combos, so this moves only the four palettes that failed.
454
- planOn: {
455
- borderColor: theme.focus.ringColor,
456
- backgroundColor: theme.color.accentSoft
457
- },
458
- planPressed: { backgroundColor: theme.state.pressed },
459
- indicator: {
460
- width: INDICATOR.ring,
461
- height: INDICATOR.ring,
462
- flexShrink: 0,
463
- alignItems: "center",
464
- justifyContent: "center",
465
- borderRadius: theme.radius.full,
466
- borderWidth: theme.borderWidth.thick,
467
- borderColor: theme.color.borderStrong
468
- },
469
- // The radio ring's selected edge, on the same footing as `planOn` above.
470
- indicatorOn: { borderColor: theme.focus.ringColor },
471
- indicatorDot: {
472
- width: INDICATOR.dot,
473
- height: INDICATOR.dot,
474
- borderRadius: theme.radius.full,
475
- backgroundColor: theme.color.accent
476
- },
477
- planMain: { flex: 1, minWidth: 0, gap: theme.space.s1 },
478
- planTitle: {
479
- fontFamily: theme.font.sans,
480
- fontWeight: theme.fontWeight.bold,
481
- fontSize: theme.type.subheadline.fontSize,
482
- lineHeight: theme.type.subheadline.lineHeight,
483
- letterSpacing: theme.type.subheadline.letterSpacing,
484
- color: theme.color.text
485
- },
486
- planNote: {
487
- fontFamily: theme.font.sans,
488
- fontSize: theme.type.caption1.fontSize,
489
- lineHeight: theme.type.caption1.lineHeight,
490
- color: theme.color.text2
491
- },
492
- footer: {
493
- padding: theme.layout.screenPad,
494
- gap: theme.space.s2,
495
- borderTopWidth: theme.borderWidth.base,
496
- borderTopColor: theme.color.border,
497
- backgroundColor: theme.color.bg
498
- },
499
- legal: {
500
- fontFamily: theme.font.sans,
501
- fontSize: theme.type.caption2.fontSize,
502
- lineHeight: theme.type.caption2.fontSize * theme.lineHeight.normal,
503
- color: theme.color.text3,
504
- textAlign: "center"
505
- },
506
- links: {
507
- flexDirection: "row",
508
- justifyContent: "center",
509
- flexWrap: "wrap",
510
- gap: theme.space.s4
511
- },
512
- link: {
513
- fontFamily: theme.font.sans,
514
- fontSize: theme.type.footnote.fontSize,
515
- lineHeight: theme.type.footnote.lineHeight,
516
- color: theme.color.text2
517
- },
518
- // Badge hugs with `flex-start`, which pins it to the top of this centred row.
519
- rowBadge: { alignSelf: "flex-start" }
520
- }));
521
- var WEB_BLUR = Platform.OS === "web";
522
- var FADE_STEPS = [0.25, 0.5, 0.75, 0.92];
523
- function PaywallGate({
524
- children,
525
- locked = true,
526
- treatment = "blur",
527
- title,
528
- description,
529
- planLabel,
530
- actionLabel,
531
- onAction,
532
- secondaryLabel,
533
- onSecondary,
534
- previewHeight,
535
- size = "regular",
536
- BlurComponent,
537
- style
538
- }) {
539
- const { styles, theme } = useStyles(sheet3);
540
- if (!locked) return /* @__PURE__ */ jsx(View, { style, children });
541
- const compact = size === "compact";
542
- const fade = treatment === "fade";
543
- const preview = previewHeight ?? theme.panel.xs;
544
- const card = /* @__PURE__ */ jsxs(
545
- View,
546
- {
547
- accessibilityRole: "summary",
548
- accessibilityLabel: title,
549
- style: [styles.card, compact ? styles.cardCompact : styles.cardRegular],
550
- children: [
551
- /* @__PURE__ */ jsx(View, { style: [styles.lock, compact ? styles.lockCompact : styles.lockRegular], children: /* @__PURE__ */ jsx(
552
- Icon,
553
- {
554
- name: "lock",
555
- size: compact ? theme.icon.sm : theme.icon.md,
556
- color: theme.color.accentOnSoft
557
- }
558
- ) }),
559
- /* @__PURE__ */ jsxs(View, { style: styles.copy, children: [
560
- planLabel ? /* @__PURE__ */ jsx(Text, { style: styles.plan, children: planLabel }) : null,
561
- /* @__PURE__ */ jsx(Text, { accessibilityRole: "header", style: styles.title, children: title }),
562
- description ? /* @__PURE__ */ jsx(Text, { style: styles.description, children: description }) : null
563
- ] }),
564
- /* @__PURE__ */ jsxs(View, { style: styles.actions, children: [
565
- /* @__PURE__ */ jsx(Button, { size: "sm", variant: "primary", onPress: onAction, children: actionLabel }),
566
- secondaryLabel && onSecondary ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onPress: onSecondary, children: secondaryLabel }) : null
567
- ] })
568
- ]
569
- }
570
- );
571
- return /* @__PURE__ */ jsxs(View, { style: [styles.root, style], children: [
572
- /* @__PURE__ */ jsxs(
573
- View,
574
- {
575
- pointerEvents: "none",
576
- accessibilityElementsHidden: true,
577
- importantForAccessibility: "no-hide-descendants",
578
- "aria-hidden": true,
579
- style: [
580
- treatment === "dim" ? styles.dimmed : null,
581
- treatment === "blur" && WEB_BLUR ? (
582
- // react-native-web forwards `filter` as CSS; cast because RN's own
583
- // `filter` type is the new-architecture array form. `blur.md`
584
- // matches the web component's `--blur-md`.
585
- {
586
- filter: `blur(${theme.blur.md}px) saturate(0.6)`,
587
- opacity: theme.opacity[72]
588
- }
589
- ) : null,
590
- fade ? { maxHeight: preview + theme.space.s8, overflow: "hidden" } : null
591
- ],
592
- children: [
593
- children,
594
- treatment === "blur" ? BlurComponent ? /* @__PURE__ */ jsx(BlurComponent, { intensity: 40, style: styles.fill }) : WEB_BLUR ? null : /* @__PURE__ */ jsx(View, { style: [styles.fill, styles.veil] }) : null,
595
- fade ? /* @__PURE__ */ jsx(View, { style: styles.fadeBands, children: FADE_STEPS.map((opacity) => /* @__PURE__ */ jsx(View, { style: [styles.fadeBand, { opacity }] }, opacity)) }) : null
596
- ]
597
- }
598
- ),
599
- /* @__PURE__ */ jsx(View, { style: fade ? styles.slotAfter : styles.slotOver, children: card })
600
- ] });
601
- }
602
- var sheet3 = createStyleSheet((theme) => ({
603
- root: { position: "relative", overflow: "hidden" },
604
- fill: { position: "absolute", top: 0, right: 0, bottom: 0, left: 0 },
605
- // The frosted fallback: opaque enough that no row of sample text is
606
- // legible through it, translucent enough that the shape still shows.
607
- veil: { backgroundColor: theme.color.surface, opacity: theme.opacity[72] },
608
- dimmed: { opacity: theme.state.disabledOpacity },
609
- fadeBands: { position: "absolute", left: 0, right: 0, bottom: 0 },
610
- fadeBand: { height: theme.space.s2, backgroundColor: theme.color.bg },
611
- slotOver: {
612
- position: "absolute",
613
- top: 0,
614
- right: 0,
615
- bottom: 0,
616
- left: 0,
617
- alignItems: "center",
618
- justifyContent: "center",
619
- padding: theme.space.s4
620
- },
621
- slotAfter: { alignItems: "center", marginTop: -theme.space.s6, padding: theme.space.s4 },
622
- card: {
623
- width: "100%",
624
- alignItems: "center",
625
- gap: theme.space.s3,
626
- borderRadius: theme.radius.lg,
627
- borderWidth: theme.borderWidth.base,
628
- borderColor: theme.color.border,
629
- backgroundColor: theme.color.surface,
630
- ...theme.shadow.md
631
- },
632
- cardRegular: { maxWidth: theme.panel.xl, padding: theme.space.s5 },
633
- cardCompact: { maxWidth: theme.panel.lg, padding: theme.space.s4 },
634
- lock: {
635
- alignItems: "center",
636
- justifyContent: "center",
637
- borderRadius: theme.radius.full,
638
- backgroundColor: theme.color.accentSoft,
639
- borderWidth: theme.borderWidth.base,
640
- borderColor: theme.edge.accent
641
- },
642
- lockRegular: { width: theme.ctl.md, height: theme.ctl.md },
643
- lockCompact: { width: theme.ctl.sm, height: theme.ctl.sm },
644
- copy: { alignItems: "center", gap: theme.space.s1 },
645
- plan: {
646
- fontFamily: theme.font.sans,
647
- fontWeight: theme.fontWeight.bold,
648
- fontSize: theme.type.caption2.fontSize,
649
- lineHeight: theme.type.caption2.lineHeight,
650
- letterSpacing: theme.tracking.caps,
651
- textTransform: "uppercase",
652
- color: theme.color.accentStrong
653
- },
654
- title: {
655
- fontFamily: theme.font.sans,
656
- fontWeight: theme.fontWeight.bold,
657
- fontSize: theme.fontSize[14],
658
- color: theme.color.text,
659
- textAlign: "center"
660
- },
661
- description: {
662
- fontFamily: theme.font.sans,
663
- fontSize: theme.type.footnote.fontSize,
664
- lineHeight: theme.type.footnote.fontSize * theme.lineHeight.normal,
665
- color: theme.color.text2,
666
- textAlign: "center"
667
- },
668
- actions: {
669
- flexDirection: "row",
670
- flexWrap: "wrap",
671
- justifyContent: "center",
672
- gap: theme.space.s2
673
- }
674
- }));
675
- function MeterBar({
676
- value,
677
- max,
678
- unit,
679
- tone = "accent",
680
- label,
681
- caption,
682
- size = "md",
683
- animate = false,
684
- accessibilityLabel,
685
- labels: labelsProp,
686
- style
687
- }) {
688
- const { styles } = useStyles(sheet4);
689
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
690
- const locale = useLoamLocale();
691
- const readout = labels.meterReadout(value.toLocaleString(locale), max.toLocaleString(locale), unit);
692
- const name = accessibilityLabel ?? (label ? `${label}: ${readout}` : readout);
693
- return /* @__PURE__ */ jsxs(View, { style: [styles.block, style], children: [
694
- label == null && unit == null ? null : /* @__PURE__ */ jsxs(View, { style: styles.readoutRow, children: [
695
- label == null ? null : /* @__PURE__ */ jsx(Text, { style: styles.label, children: label }),
696
- /* @__PURE__ */ jsx(View, { style: styles.pushEnd, children: /* @__PURE__ */ jsx(Text, { style: styles.readout, children: readout }) })
697
- ] }),
698
- /* @__PURE__ */ jsx(
699
- Progress,
700
- {
701
- value,
702
- max,
703
- size,
704
- tone,
705
- animateValue: animate,
706
- accessibilityLabel: name
707
- }
708
- ),
709
- caption ? /* @__PURE__ */ jsx(Text, { style: styles.caption, children: caption }) : null
710
- ] });
711
- }
712
- var sheet4 = createStyleSheet((theme) => ({
713
- block: { alignSelf: "stretch", gap: theme.space.s1 },
714
- readoutRow: {
715
- flexDirection: "row",
716
- flexWrap: "wrap",
717
- alignItems: "baseline",
718
- gap: theme.space.s2
719
- },
720
- label: {
721
- flexShrink: 1,
722
- fontFamily: theme.font.sans,
723
- fontSize: theme.type.footnote.fontSize,
724
- lineHeight: theme.type.footnote.lineHeight,
725
- color: theme.color.text2
726
- },
727
- pushEnd: { marginStart: "auto" },
728
- readout: {
729
- fontFamily: theme.font.sans,
730
- fontWeight: theme.fontWeight.bold,
731
- fontVariant: ["tabular-nums"],
732
- fontSize: theme.type.footnote.fontSize,
733
- lineHeight: theme.type.footnote.lineHeight,
734
- color: theme.color.text
735
- },
736
- caption: {
737
- fontFamily: theme.font.sans,
738
- fontSize: theme.type.caption1.fontSize,
739
- lineHeight: theme.type.caption1.fontSize * theme.lineHeight.normal,
740
- color: theme.color.text3
741
- }
742
- }));
743
- function SavingsChip({
744
- savingMinor,
745
- plan,
746
- currency,
747
- label,
748
- per,
749
- locale,
750
- labels: labelsProp,
751
- style
752
- }) {
753
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
754
- const theme = useLoamTheme("commerce");
755
- const { styles } = useStyles(sheet5);
756
- const saving = savingMinor ?? (plan ? yearlySaving(plan) : null);
757
- if (saving == null) return null;
758
- return /* @__PURE__ */ jsxs(View, { style: [styles.savingChip, style], children: [
759
- /* @__PURE__ */ jsx(Text, { style: styles.savingWord, children: label ?? labels.save }),
760
- /* @__PURE__ */ jsx(
761
- Amount,
762
- {
763
- minor: saving,
764
- currency,
765
- size: "sm",
766
- weight: "bold",
767
- locale,
768
- style: { color: theme.color.goodOnSoft }
769
- }
770
- ),
771
- /* @__PURE__ */ jsx(Text, { style: styles.savingWord, children: per ?? labels.perYear })
772
- ] });
773
- }
774
- function PlanPriceDelta({
775
- fromMinor,
776
- toMinor,
777
- currency,
778
- unit,
779
- sameLabel,
780
- locale,
781
- labels: labelsProp,
782
- style
783
- }) {
784
- const { styles } = useStyles(sheet5);
785
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
786
- const pay = usePayLabels(labelsProp);
787
- const delta = planDelta(fromMinor, toMinor);
788
- if (delta === 0) {
789
- return /* @__PURE__ */ jsx(Text, { style: [styles.deltaUnit, style], children: sameLabel ?? labels.samePrice });
790
- }
791
- return /* @__PURE__ */ jsxs(View, { style: [styles.deltaRow, style], children: [
792
- /* @__PURE__ */ jsx(
793
- Amount,
794
- {
795
- minor: delta,
796
- currency,
797
- size: "sm",
798
- weight: "bold",
799
- signed: true,
800
- tone: delta > 0 ? "warn" : "good",
801
- locale
802
- }
803
- ),
804
- /* @__PURE__ */ jsx(Text, { style: styles.deltaUnit, children: unit ?? pay.perSeat })
805
- ] });
806
- }
807
- function PlanFeatureRow({
808
- label,
809
- included = true,
810
- detail,
811
- stateLabel,
812
- labels: labelsProp,
813
- style
814
- }) {
815
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
816
- const theme = useLoamTheme("commerce");
817
- const { styles } = useStyles(sheet5);
818
- const state = stateLabel ?? (included ? labels.included : labels.notIncluded);
819
- return /* @__PURE__ */ jsxs(
820
- View,
821
- {
822
- role: "listitem",
823
- accessibilityLabel: `${labels.featureState(state)}${label}${detail ? `. ${detail}` : ""}`,
824
- style: [styles.featureRow, style],
825
- children: [
826
- /* @__PURE__ */ jsx(
827
- Icon,
828
- {
829
- name: included ? "check" : "minus",
830
- size: theme.icon.sm,
831
- color: included ? theme.color.good : theme.color.text3
832
- }
833
- ),
834
- /* @__PURE__ */ jsxs(View, { style: styles.featureBody, children: [
835
- /* @__PURE__ */ jsx(Text, { style: included ? styles.featureLabel : styles.featureLabelOut, children: label }),
836
- detail ? /* @__PURE__ */ jsx(Text, { style: styles.featureDetail, children: detail }) : null
837
- ] })
838
- ]
839
- }
840
- );
841
- }
842
- function PlanPriceCell({
843
- plan,
844
- currency,
845
- cadence = "mo",
846
- size = "lg",
847
- savingMinor,
848
- locale,
849
- labels: labelsProp,
850
- style,
851
- motion = "full"
852
- }) {
853
- const { styles } = useStyles(sheet5);
854
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
855
- const pay = usePayLabels(labelsProp);
856
- const words = planCta(plan, pay).price;
857
- const perMonth = yearlyMonthly(plan);
858
- const yearly = cadence === "yr" && plan.yearly != null ? plan.yearly : null;
859
- const headline = yearly != null && perMonth != null ? perMonth : plan.price;
860
- return /* @__PURE__ */ jsxs(View, { style: [styles.priceCell, style], children: [
861
- /* @__PURE__ */ jsx(View, { style: styles.priceHeadline, children: words ? /* @__PURE__ */ jsx(Text, { style: size === "hero" ? styles.priceWordsHero : styles.priceWords, children: words }) : headline == null ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
862
- /* @__PURE__ */ jsx(
863
- Amount,
864
- {
865
- minor: headline,
866
- currency,
867
- size,
868
- weight: "bold",
869
- locale,
870
- roll: true,
871
- motion
872
- }
873
- ),
874
- /* @__PURE__ */ jsx(Text, { style: styles.priceUnit, children: pay.perSeat })
875
- ] }) }),
876
- yearly == null ? null : /* @__PURE__ */ jsxs(View, { style: styles.yearlyRow, children: [
877
- /* @__PURE__ */ jsx(Amount, { minor: yearly, currency, size: "sm", weight: "bold", locale }),
878
- /* @__PURE__ */ jsx(Text, { style: styles.priceUnit, children: labels.billedYearlyTail }),
879
- /* @__PURE__ */ jsx(
880
- SavingsChip,
881
- {
882
- savingMinor,
883
- plan,
884
- currency,
885
- locale,
886
- labels: labelsProp
887
- }
888
- )
889
- ] })
890
- ] });
891
- }
892
- function PlanCard({
893
- plan,
894
- currency,
895
- cadence = "mo",
896
- highlighted,
897
- isCurrent = false,
898
- savingMinor,
899
- ctaLabel,
900
- currentLabel: currentLabelProp,
901
- onSelect,
902
- loading = false,
903
- locked = false,
904
- locale,
905
- labels: labelsProp,
906
- style
907
- }) {
908
- const theme = useLoamTheme("commerce");
909
- const { styles } = useStyles(sheet5);
910
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
911
- const pay = usePayLabels(labelsProp);
912
- const currentLabel = currentLabelProp ?? labels.yourPlan;
913
- const recommended = highlighted ?? plan.popular ?? false;
914
- return /* @__PURE__ */ jsxs(
915
- View,
916
- {
917
- testID: `plan-card-${plan.id}`,
918
- style: [
919
- styles.card,
920
- recommended ? styles.cardRecommended : styles.cardPlain,
921
- // `current` adds the accent tint so "this one is yours" survives next to
922
- // a highlighted neighbour.
923
- isCurrent ? styles.cardCurrent : null,
924
- style
925
- ],
926
- children: [
927
- /* @__PURE__ */ jsxs(View, { style: styles.cardHead, children: [
928
- /* @__PURE__ */ jsx(Text, { accessibilityRole: "header", style: styles.planName, children: plan.name }),
929
- recommended ? /* @__PURE__ */ jsx(Badge, { style: styles.rowBadge, variant: "accent", size: "sm", children: pay.popularBadge }) : null,
930
- isCurrent ? /* @__PURE__ */ jsx(Badge, { variant: "neutral", size: "sm", outline: true, children: currentLabel }) : null
931
- ] }),
932
- /* @__PURE__ */ jsx(
933
- PlanPriceCell,
934
- {
935
- plan,
936
- currency,
937
- cadence,
938
- savingMinor,
939
- locale,
940
- labels: labelsProp
941
- }
942
- ),
943
- /* @__PURE__ */ jsx(Text, { style: styles.blurb, children: plan.blurb }),
944
- /* @__PURE__ */ jsx(View, { style: styles.rule }),
945
- /* @__PURE__ */ jsx(View, { role: "list", accessibilityRole: "list", style: styles.featureList, children: plan.features.map((feature) => /* @__PURE__ */ jsx(PlanFeatureRow, { label: feature, labels: labelsProp }, feature)) }),
946
- isCurrent ? (
947
- // Not a disabled button: a dead control invites the press that teaches
948
- // nothing. The marker states the fact and takes no tab stop.
949
- /* @__PURE__ */ jsxs(View, { style: styles.currentMarker, children: [
950
- /* @__PURE__ */ jsx(Icon, { name: "check-circle", size: theme.icon.sm, color: theme.color.good }),
951
- /* @__PURE__ */ jsx(Text, { style: styles.currentMarkerLabel, children: currentLabel })
952
- ] })
953
- ) : /* @__PURE__ */ jsx(
954
- Button,
955
- {
956
- fullWidth: true,
957
- variant: recommended ? "primary" : "outline",
958
- loading,
959
- onPress: locked ? void 0 : () => onSelect?.(plan.id),
960
- children: ctaLabel ?? planCta(plan, pay).cta
961
- }
962
- )
963
- ]
964
- }
965
- );
966
- }
967
- function BillingPeriodToggle({
968
- value,
969
- onValueChange,
970
- monthlyLabel,
971
- yearlyLabel,
972
- size = "md",
973
- savingMinor,
974
- currency,
975
- locale,
976
- labels: labelsProp,
977
- style
978
- }) {
979
- const { styles } = useStyles(sheet5);
980
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
981
- const pay = usePayLabels(labelsProp);
982
- return /* @__PURE__ */ jsxs(View, { style: [styles.toggleRow, style], children: [
983
- /* @__PURE__ */ jsx(
984
- SegmentedControl,
985
- {
986
- accessibilityLabel: labels.billingPeriod,
987
- size,
988
- value,
989
- onValueChange: (next) => onValueChange(next),
990
- items: [
991
- { value: "mo", label: monthlyLabel ?? pay.cadenceMonthly },
992
- { value: "yr", label: yearlyLabel ?? pay.cadenceYearly }
993
- ]
994
- }
995
- ),
996
- savingMinor != null && currency ? /* @__PURE__ */ jsx(
997
- SavingsChip,
998
- {
999
- savingMinor,
1000
- currency,
1001
- locale,
1002
- labels: labelsProp
1003
- }
1004
- ) : null
1005
- ] });
1006
- }
1007
- function PlanGrid({
1008
- plans,
1009
- currency,
1010
- cadence,
1011
- onCadenceChange,
1012
- onSelect,
1013
- currentPlanId,
1014
- pendingPlanId,
1015
- savings,
1016
- hideIds,
1017
- locale,
1018
- labels: labelsProp,
1019
- style
1020
- }) {
1021
- const { styles } = useStyles(sheet5);
1022
- const shown = hideIds?.length ? plans.filter((plan) => !hideIds.includes(plan.id)) : plans;
1023
- return /* @__PURE__ */ jsxs(View, { style: [styles.grid, style], children: [
1024
- onCadenceChange ? /* @__PURE__ */ jsx(
1025
- BillingPeriodToggle,
1026
- {
1027
- value: cadence,
1028
- onValueChange: onCadenceChange,
1029
- currency,
1030
- locale,
1031
- labels: labelsProp
1032
- }
1033
- ) : null,
1034
- /* @__PURE__ */ jsx(View, { style: styles.gridStack, children: shown.map((plan) => /* @__PURE__ */ jsx(
1035
- PlanCard,
1036
- {
1037
- plan,
1038
- currency,
1039
- cadence,
1040
- isCurrent: currentPlanId === plan.id,
1041
- savingMinor: savings?.[plan.id],
1042
- onSelect,
1043
- loading: pendingPlanId === plan.id,
1044
- locked: pendingPlanId != null,
1045
- locale,
1046
- labels: labelsProp
1047
- },
1048
- plan.id
1049
- )) })
1050
- ] });
1051
- }
1052
- var sheet5 = createStyleSheet((theme) => ({
1053
- savingChip: {
1054
- flexDirection: "row",
1055
- alignItems: "baseline",
1056
- alignSelf: "flex-start",
1057
- gap: theme.space.s1,
1058
- paddingHorizontal: theme.space.s2,
1059
- paddingVertical: theme.space[2],
1060
- borderRadius: theme.radius.full,
1061
- // A soft tint needs its tone edge: the fill collapses to the plain surface
1062
- // under high contrast, where the edge is the only thing drawing it.
1063
- borderWidth: theme.borderWidth.base,
1064
- borderColor: theme.edge.good,
1065
- backgroundColor: theme.color.goodSoft
1066
- },
1067
- savingWord: {
1068
- fontFamily: theme.font.sans,
1069
- fontSize: theme.type.caption1.fontSize,
1070
- lineHeight: theme.type.caption1.lineHeight,
1071
- color: theme.color.goodOnSoft
1072
- },
1073
- deltaRow: {
1074
- flexDirection: "row",
1075
- alignItems: "baseline",
1076
- alignSelf: "flex-start",
1077
- gap: theme.space.s1
1078
- },
1079
- deltaUnit: {
1080
- fontFamily: theme.font.sans,
1081
- fontSize: theme.type.footnote.fontSize,
1082
- lineHeight: theme.type.footnote.lineHeight,
1083
- color: theme.color.text3
1084
- },
1085
- featureRow: { flexDirection: "row", alignItems: "flex-start", gap: theme.space.s2 },
1086
- featureBody: { flex: 1, gap: theme.space[2] },
1087
- featureLabel: {
1088
- fontFamily: theme.font.sans,
1089
- fontSize: theme.type.footnote.fontSize,
1090
- lineHeight: theme.type.footnote.fontSize * theme.lineHeight.normal,
1091
- color: theme.color.text2
1092
- },
1093
- featureLabelOut: {
1094
- fontFamily: theme.font.sans,
1095
- fontSize: theme.type.footnote.fontSize,
1096
- lineHeight: theme.type.footnote.fontSize * theme.lineHeight.normal,
1097
- color: theme.color.text3
1098
- },
1099
- featureDetail: {
1100
- fontFamily: theme.font.sans,
1101
- fontSize: theme.type.caption1.fontSize,
1102
- lineHeight: theme.type.caption1.lineHeight,
1103
- color: theme.color.text3
1104
- },
1105
- priceCell: { gap: theme.space.s1 },
1106
- priceHeadline: {
1107
- flexDirection: "row",
1108
- flexWrap: "wrap",
1109
- alignItems: "baseline",
1110
- columnGap: theme.space.s2,
1111
- rowGap: theme.space.s1
1112
- },
1113
- priceWords: {
1114
- fontFamily: theme.font.sans,
1115
- fontWeight: theme.fontWeight.bold,
1116
- fontSize: theme.type.title3.fontSize,
1117
- lineHeight: theme.type.title3.lineHeight,
1118
- color: theme.color.text
1119
- },
1120
- priceWordsHero: {
1121
- fontFamily: theme.font.sans,
1122
- fontWeight: theme.fontWeight.bold,
1123
- fontSize: theme.fontSize[32],
1124
- lineHeight: theme.fontSize[32] * theme.lineHeight.tight,
1125
- color: theme.color.text
1126
- },
1127
- priceUnit: {
1128
- fontFamily: theme.font.sans,
1129
- fontSize: theme.type.footnote.fontSize,
1130
- lineHeight: theme.type.footnote.lineHeight,
1131
- color: theme.color.text3
1132
- },
1133
- yearlyRow: {
1134
- flexDirection: "row",
1135
- flexWrap: "wrap",
1136
- alignItems: "baseline",
1137
- gap: theme.space.s2
1138
- },
1139
- card: {
1140
- alignSelf: "stretch",
1141
- gap: theme.space.s4,
1142
- padding: theme.space.s5,
1143
- borderRadius: theme.radius.lg,
1144
- backgroundColor: theme.color.surface
1145
- },
1146
- cardPlain: { borderWidth: theme.borderWidth.base, borderColor: theme.color.border },
1147
- // `focus.ringColor`, not the raw accent: this border is what marks the
1148
- // recommended plan, and it is a graphical object under SC 1.4.11 either way.
1149
- // Identical to the raw accent in 9 of the 14 palette × mode combos, so it
1150
- // moves only the four that failed. Same call `paywall.tsx` makes for `planOn`.
1151
- cardRecommended: {
1152
- borderWidth: theme.borderWidth.heavy,
1153
- borderColor: theme.focus.ringColor,
1154
- ...theme.shadow.md
1155
- },
1156
- cardCurrent: { backgroundColor: theme.color.accentSoft, borderColor: theme.edge.accent },
1157
- cardHead: {
1158
- flexDirection: "row",
1159
- flexWrap: "wrap",
1160
- alignItems: "center",
1161
- gap: theme.space.s2
1162
- },
1163
- planName: {
1164
- fontFamily: theme.font.sans,
1165
- fontWeight: theme.fontWeight.bold,
1166
- fontSize: theme.type.subheadline.fontSize,
1167
- lineHeight: theme.type.subheadline.lineHeight,
1168
- color: theme.color.text
1169
- },
1170
- blurb: {
1171
- fontFamily: theme.font.sans,
1172
- fontSize: theme.type.footnote.fontSize,
1173
- lineHeight: theme.type.footnote.fontSize * theme.lineHeight.normal,
1174
- color: theme.color.text2
1175
- },
1176
- rule: { height: theme.borderWidth.base, backgroundColor: theme.color.border },
1177
- featureList: { gap: theme.space.s2 },
1178
- currentMarker: {
1179
- flexDirection: "row",
1180
- alignItems: "center",
1181
- justifyContent: "center",
1182
- gap: theme.space.s1,
1183
- paddingVertical: theme.space.s2,
1184
- borderRadius: theme.radius.md,
1185
- borderWidth: theme.borderWidth.base,
1186
- borderColor: theme.color.border
1187
- },
1188
- currentMarkerLabel: {
1189
- fontFamily: theme.font.sans,
1190
- fontWeight: theme.fontWeight.bold,
1191
- fontSize: theme.type.footnote.fontSize,
1192
- lineHeight: theme.type.footnote.lineHeight,
1193
- color: theme.color.text2
1194
- },
1195
- toggleRow: {
1196
- flexDirection: "row",
1197
- flexWrap: "wrap",
1198
- alignItems: "center",
1199
- justifyContent: "center",
1200
- gap: theme.space.s3
1201
- },
1202
- grid: { alignSelf: "stretch", gap: theme.space.s5 },
1203
- gridStack: { gap: theme.space.s4 },
1204
- // Badge hugs with `flex-start`, which pins it to the top of this centred row.
1205
- rowBadge: { alignSelf: "center" }
1206
- }));
1207
- function prorationWay(proration) {
1208
- return proration.dueNow === 0 && proration.refund > 0 ? "downgrade" : "upgrade";
1209
- }
1210
- function ProrationLine({
1211
- proration,
1212
- currency,
1213
- effectiveLabel,
1214
- nextMinor,
1215
- nextCadenceLabel,
1216
- locale,
1217
- labels: labelsProp,
1218
- style
1219
- }) {
1220
- const { styles } = useStyles(sheet6);
1221
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
1222
- const downgrade = prorationWay(proration) === "downgrade";
1223
- return /* @__PURE__ */ jsxs(View, { style: [styles.prorationLine, style], children: [
1224
- /* @__PURE__ */ jsx(
1225
- Amount,
1226
- {
1227
- minor: downgrade ? proration.refund : proration.dueNow,
1228
- currency,
1229
- size: "sm",
1230
- weight: "bold",
1231
- tone: downgrade ? "good" : "default",
1232
- locale
1233
- }
1234
- ),
1235
- /* @__PURE__ */ jsx(Text, { style: styles.prorationWord, children: downgrade ? labels.creditedNextInvoice : labels.today }),
1236
- nextMinor == null ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
1237
- /* @__PURE__ */ jsx(Text, { style: styles.prorationSep, children: "\xB7" }),
1238
- /* @__PURE__ */ jsx(Text, { style: styles.prorationWord, children: labels.then }),
1239
- /* @__PURE__ */ jsx(Amount, { minor: nextMinor, currency, size: "sm", weight: "bold", locale }),
1240
- /* @__PURE__ */ jsx(Text, { style: styles.prorationWord, children: labels.cadenceFrom(nextCadenceLabel ?? labels.monthly, effectiveLabel) })
1241
- ] })
1242
- ] });
1243
- }
1244
- function ProrationTable({
1245
- proration,
1246
- currency,
1247
- fromName,
1248
- toName,
1249
- daysLeft = proration.daysLeft,
1250
- cycleDays = proration.cycleDays,
1251
- effectiveLabel,
1252
- nextMinor,
1253
- nextCadenceLabel,
1254
- caption,
1255
- note,
1256
- locale,
1257
- labels: labelsProp,
1258
- style
1259
- }) {
1260
- const { styles } = useStyles(sheet6);
1261
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
1262
- const pay = usePayLabels(labelsProp);
1263
- const downgrade = prorationWay(proration) === "downgrade";
1264
- return /* @__PURE__ */ jsxs(View, { style: [styles.prorationTable, style], children: [
1265
- /* @__PURE__ */ jsx(Text, { style: styles.overline, children: caption ?? labels.midCycleChange(currency) }),
1266
- /* @__PURE__ */ jsx(
1267
- PriceRow,
1268
- {
1269
- label: labels.unusedTime(fromName, daysLeft, cycleDays),
1270
- minor: -proration.credit,
1271
- currency,
1272
- tone: "good",
1273
- noSymbol: true,
1274
- locale
1275
- }
1276
- ),
1277
- /* @__PURE__ */ jsx(
1278
- PriceRow,
1279
- {
1280
- label: labels.sameDays(toName, daysLeft),
1281
- minor: proration.charge,
1282
- currency,
1283
- noSymbol: true,
1284
- locale
1285
- }
1286
- ),
1287
- /* @__PURE__ */ jsx(
1288
- PriceRow,
1289
- {
1290
- label: downgrade ? labels.creditOnNextInvoice : labels.chargedToday,
1291
- minor: downgrade ? proration.refund : proration.dueNow,
1292
- currency,
1293
- tone: downgrade ? "good" : void 0,
1294
- strong: true,
1295
- rule: true,
1296
- noSymbol: true,
1297
- locale
1298
- }
1299
- ),
1300
- nextMinor == null ? null : /* @__PURE__ */ jsx(
1301
- PriceRow,
1302
- {
1303
- label: labels.fromDate(effectiveLabel, nextCadenceLabel ?? labels.monthly),
1304
- minor: nextMinor,
1305
- currency,
1306
- noSymbol: true,
1307
- locale
1308
- }
1309
- ),
1310
- note === false ? null : /* @__PURE__ */ jsx(Text, { style: styles.prorationNote, children: note === void 0 ? pay.prorationNote : note })
1311
- ] });
1312
- }
1313
- function toPaywallPlan(plan, currency, cadence, savingMinor, isCurrent, currentLabel, locale, labels, pay) {
1314
- const words = planCta(plan, pay).price;
1315
- const perMonth = yearlyMonthly(plan);
1316
- const yearly = cadence === "yr" && plan.yearly != null ? plan.yearly : null;
1317
- const headline = yearly != null && perMonth != null ? perMonth : plan.price;
1318
- const saving = savingMinor ?? yearlySaving(plan);
1319
- const notes = [];
1320
- if (yearly != null) notes.push(`${money(yearly, currency, { locale })} ${labels.billedYearlyTail}`);
1321
- if (yearly != null && saving != null) {
1322
- notes.push(`${labels.save} ${money(saving, currency, { locale })} ${labels.perYear}`);
1323
- }
1324
- notes.push(plan.blurb);
1325
- if (isCurrent) notes.push(currentLabel);
1326
- return {
1327
- id: plan.id,
1328
- name: plan.name,
1329
- price: words || (headline == null ? "" : money(headline, currency, { locale })),
1330
- period: words ? "" : pay.perSeat,
1331
- note: notes.join(" \xB7 "),
1332
- recommended: plan.popular ?? false,
1333
- recommendedLabel: pay.popularBadge
1334
- };
1335
- }
1336
- function PaywallSurface({
1337
- variant = "hard",
1338
- title,
1339
- subtitle,
1340
- meter,
1341
- plans,
1342
- currency,
1343
- cadence,
1344
- onCadenceChange,
1345
- onPickPlan,
1346
- currentPlanId,
1347
- pendingPlanId,
1348
- currentLabel: currentLabelProp,
1349
- savings,
1350
- hideIds,
1351
- featureOffer,
1352
- billing = "ours",
1353
- platformNote: platformNoteProp,
1354
- legalText,
1355
- footNote,
1356
- dismissLabel: dismissLabelProp,
1357
- onDismiss,
1358
- restoreLabel: restoreLabelProp,
1359
- onRestore,
1360
- upgradeLabel,
1361
- onUpgrade,
1362
- locale: localeProp,
1363
- labels: labelsProp,
1364
- style
1365
- }) {
1366
- const { styles } = useStyles(sheet6);
1367
- const labels = useLabels("paywall", DEFAULT_LABELS, labelsProp);
1368
- const pay = usePayLabels(labelsProp);
1369
- const providerLocale = useLoamLocale();
1370
- const locale = localeProp ?? providerLocale;
1371
- const currentLabel = currentLabelProp ?? labels.yourPlan;
1372
- const platformNote = platformNoteProp ?? labels.platformNote;
1373
- const dismissLabel = dismissLabelProp ?? labels.notNow;
1374
- const restoreLabel = restoreLabelProp ?? labels.restorePurchases;
1375
- const canDismiss = variant !== "hard" && Boolean(onDismiss);
1376
- const showMeter = (variant === "metered" || variant === "trial") && meter != null;
1377
- const offer = variant === "feature" ? featureOffer : void 0;
1378
- const shown = React2.useMemo(() => {
1379
- const list = plans ?? [];
1380
- return hideIds?.length ? list.filter((p) => !hideIds.includes(p.id)) : list;
1381
- }, [plans, hideIds]);
1382
- const [selected, setSelected] = React2.useState(
1383
- () => shown.find((p) => p.popular)?.id ?? shown[0]?.id
1384
- );
1385
- const selectedPlan = shown.find((p) => p.id === selected);
1386
- const footer = /* @__PURE__ */ jsx(View, { style: styles.footerNotes, children: footNote ? /* @__PURE__ */ jsx(Text, { style: styles.footNote, children: footNote }) : null });
1387
- const slot = /* @__PURE__ */ jsxs(View, { style: styles.slot, children: [
1388
- billing === "platform" ? /* @__PURE__ */ jsx(Text, { style: styles.platformNote, children: platformNote }) : null,
1389
- showMeter && meter ? /* @__PURE__ */ jsx(MeterBar, { labels: labelsProp, ...meter }) : null,
1390
- onCadenceChange ? /* @__PURE__ */ jsx(
1391
- BillingPeriodToggle,
1392
- {
1393
- value: cadence,
1394
- onValueChange: onCadenceChange,
1395
- locale,
1396
- labels: labelsProp
1397
- }
1398
- ) : null
1399
- ] });
1400
- if (offer) {
1401
- return /* @__PURE__ */ jsxs(View, { role: "region", accessibilityLabel: title, style: [styles.featureSurface, style], children: [
1402
- /* @__PURE__ */ jsxs(View, { style: styles.featureHead, children: [
1403
- /* @__PURE__ */ jsx(Text, { accessibilityRole: "header", style: styles.featureTitle, children: title }),
1404
- subtitle ? /* @__PURE__ */ jsx(Text, { style: styles.featureSubtitle, children: subtitle }) : null
1405
- ] }),
1406
- billing === "platform" ? /* @__PURE__ */ jsx(Text, { style: styles.platformNote, children: platformNote }) : null,
1407
- /* @__PURE__ */ jsx(
1408
- PlanCard,
1409
- {
1410
- plan: offer.plan,
1411
- currency,
1412
- cadence,
1413
- savingMinor: offer.savingMinor,
1414
- highlighted: true,
1415
- ctaLabel: upgradeLabel,
1416
- loading: pendingPlanId === offer.plan.id,
1417
- locked: pendingPlanId != null,
1418
- onSelect: () => {
1419
- onUpgrade?.();
1420
- onPickPlan?.(offer.plan.id);
1421
- },
1422
- locale,
1423
- labels: labelsProp,
1424
- currentLabel: currentLabelProp
1425
- }
1426
- ),
1427
- offer.proration && offer.effectiveLabel ? /* @__PURE__ */ jsx(
1428
- ProrationLine,
1429
- {
1430
- proration: offer.proration,
1431
- currency,
1432
- effectiveLabel: offer.effectiveLabel,
1433
- nextMinor: offer.nextMinor,
1434
- locale,
1435
- labels: labelsProp
1436
- }
1437
- ) : null,
1438
- /* @__PURE__ */ jsx(Text, { style: styles.legal, children: legalText }),
1439
- footNote ? /* @__PURE__ */ jsx(Text, { style: styles.footNote, children: footNote }) : null,
1440
- /* @__PURE__ */ jsxs(View, { style: styles.featureActions, children: [
1441
- /* @__PURE__ */ jsx(Pressable, { accessibilityRole: "button", accessibilityLabel: restoreLabel, onPress: onRestore, children: /* @__PURE__ */ jsx(Text, { style: styles.link, children: restoreLabel }) }),
1442
- canDismiss ? /* @__PURE__ */ jsx(
1443
- Pressable,
1444
- {
1445
- accessibilityRole: "button",
1446
- accessibilityLabel: dismissLabel,
1447
- onPress: onDismiss,
1448
- children: /* @__PURE__ */ jsx(Text, { style: styles.link, children: dismissLabel })
1449
- }
1450
- ) : null
1451
- ] })
1452
- ] });
1453
- }
1454
- return /* @__PURE__ */ jsx(View, { style: [styles.surface, style], children: /* @__PURE__ */ jsx(
1455
- Paywall,
1456
- {
1457
- title,
1458
- description: subtitle,
1459
- meter: slot,
1460
- plans: shown.map(
1461
- (plan) => toPaywallPlan(
1462
- plan,
1463
- currency,
1464
- cadence,
1465
- savings?.[plan.id],
1466
- currentPlanId === plan.id,
1467
- currentLabel,
1468
- locale,
1469
- labels,
1470
- pay
1471
- )
1472
- ),
1473
- selectedPlanId: selected,
1474
- onSelectPlan: setSelected,
1475
- ctaLabel: selectedPlan ? planCta(selectedPlan, pay).cta : restoreLabel,
1476
- busy: pendingPlanId != null,
1477
- onPurchase: (id) => onPickPlan?.(id),
1478
- legalText,
1479
- footNote: footer,
1480
- restoreLabel,
1481
- onRestore,
1482
- onClose: canDismiss ? onDismiss : void 0,
1483
- closeLabel: dismissLabel,
1484
- labels: labelsProp
1485
- }
1486
- ) });
1487
- }
1488
- var sheet6 = createStyleSheet((theme) => ({
1489
- surface: { flex: 1 },
1490
- slot: { gap: theme.space.s3 },
1491
- platformNote: {
1492
- fontFamily: theme.font.sans,
1493
- fontSize: theme.type.footnote.fontSize,
1494
- lineHeight: theme.type.footnote.fontSize * theme.lineHeight.normal,
1495
- color: theme.color.text2,
1496
- textAlign: "center"
1497
- },
1498
- footerNotes: { gap: theme.space.s1 },
1499
- footNote: {
1500
- fontFamily: theme.font.sans,
1501
- fontSize: theme.type.caption2.fontSize,
1502
- lineHeight: theme.type.caption2.fontSize * theme.lineHeight.normal,
1503
- color: theme.color.text3,
1504
- textAlign: "center"
1505
- },
1506
- legal: {
1507
- fontFamily: theme.font.sans,
1508
- fontSize: theme.type.caption2.fontSize,
1509
- lineHeight: theme.type.caption2.fontSize * theme.lineHeight.normal,
1510
- color: theme.color.text3,
1511
- textAlign: "center"
1512
- },
1513
- link: {
1514
- fontFamily: theme.font.sans,
1515
- fontSize: theme.type.footnote.fontSize,
1516
- lineHeight: theme.type.footnote.lineHeight,
1517
- color: theme.color.text2
1518
- },
1519
- featureSurface: {
1520
- alignSelf: "stretch",
1521
- gap: theme.space.s4,
1522
- padding: theme.space.s5,
1523
- borderRadius: theme.radius.lg,
1524
- borderWidth: theme.borderWidth.base,
1525
- borderColor: theme.color.border,
1526
- backgroundColor: theme.color.surface
1527
- },
1528
- featureHead: { alignItems: "center", gap: theme.space.s2 },
1529
- featureTitle: {
1530
- fontFamily: theme.font.display,
1531
- fontWeight: theme.font.displayWeight,
1532
- fontSize: theme.type.title2.fontSize,
1533
- lineHeight: theme.type.title2.lineHeight,
1534
- letterSpacing: theme.type.title2.letterSpacing,
1535
- color: theme.color.text,
1536
- textAlign: "center"
1537
- },
1538
- featureSubtitle: {
1539
- fontFamily: theme.font.sans,
1540
- fontSize: theme.type.body.fontSize,
1541
- lineHeight: theme.type.body.fontSize * theme.lineHeight.normal,
1542
- color: theme.color.text2,
1543
- textAlign: "center"
1544
- },
1545
- featureActions: {
1546
- flexDirection: "row",
1547
- flexWrap: "wrap",
1548
- alignItems: "center",
1549
- justifyContent: "center",
1550
- gap: theme.space.s4
1551
- },
1552
- prorationLine: {
1553
- flexDirection: "row",
1554
- flexWrap: "wrap",
1555
- alignItems: "baseline",
1556
- columnGap: theme.space.s1,
1557
- rowGap: theme.space[2]
1558
- },
1559
- prorationWord: {
1560
- fontFamily: theme.font.sans,
1561
- fontSize: theme.type.footnote.fontSize,
1562
- lineHeight: theme.type.footnote.lineHeight,
1563
- color: theme.color.text2
1564
- },
1565
- prorationSep: {
1566
- fontFamily: theme.font.sans,
1567
- fontSize: theme.type.footnote.fontSize,
1568
- lineHeight: theme.type.footnote.lineHeight,
1569
- color: theme.color.text3
1570
- },
1571
- prorationTable: {
1572
- alignSelf: "stretch",
1573
- gap: theme.space.s2,
1574
- padding: theme.space.s4,
1575
- borderRadius: theme.radius.md,
1576
- borderWidth: theme.borderWidth.base,
1577
- borderColor: theme.color.border,
1578
- backgroundColor: theme.color.surface2
1579
- },
1580
- overline: {
1581
- fontFamily: theme.font.sans,
1582
- fontWeight: theme.fontWeight.bold,
1583
- fontSize: theme.type.caption2.fontSize,
1584
- lineHeight: theme.type.caption2.lineHeight,
1585
- letterSpacing: theme.tracking.caps,
1586
- textTransform: "uppercase",
1587
- color: theme.color.text3
1588
- },
1589
- prorationNote: {
1590
- fontFamily: theme.font.sans,
1591
- fontSize: theme.type.caption1.fontSize,
1592
- lineHeight: theme.type.caption1.fontSize * theme.lineHeight.normal,
1593
- color: theme.color.text3
1594
- }
1595
- }));
1596
- var STATUS = {
1597
- active: { variant: "good", label: "statusActive" },
1598
- trial: { variant: "info", label: "statusTrial" },
1599
- canceled: { variant: "neutral", label: "statusCanceled" },
1600
- "past-due": { variant: "warn", label: "statusPastDue" }
1601
- };
1602
- function ManageSubscription({
1603
- planName,
1604
- status = "active",
1605
- statusLabel,
1606
- price,
1607
- renewalDate,
1608
- renewalLabel: renewalLabelProp,
1609
- paymentMethod,
1610
- paymentLabel: paymentLabelProp,
1611
- actions = [],
1612
- onAction,
1613
- cancelLabel: cancelLabelProp,
1614
- onCancel,
1615
- cancelNote,
1616
- cancelBusy = false,
1617
- labels: labelsProp
1618
- }) {
1619
- const { styles } = useStyles(sheet7);
1620
- const labels = useLabels("manageSubscription", MANAGE_SUBSCRIPTION_LABELS, labelsProp);
1621
- const renewalLabel = renewalLabelProp ?? labels.renews;
1622
- const paymentLabel = paymentLabelProp ?? labels.payment;
1623
- const cancelLabel = cancelLabelProp ?? labels.cancel;
1624
- const theme = useLoamTheme("commerce");
1625
- const badge = STATUS[status];
1626
- return /* @__PURE__ */ jsxs(ScrollView, { style: styles.screen, contentContainerStyle: styles.scroll, children: [
1627
- /* @__PURE__ */ jsxs(View, { style: styles.card, children: [
1628
- /* @__PURE__ */ jsxs(View, { style: styles.cardHead, children: [
1629
- /* @__PURE__ */ jsx(Text, { style: styles.planName, children: planName }),
1630
- /* @__PURE__ */ jsx(Badge, { style: styles.rowBadge, variant: badge.variant, size: "sm", children: statusLabel ?? labels[badge.label] })
1631
- ] }),
1632
- /* @__PURE__ */ jsx(Text, { style: styles.meta, children: labels.renewalLine(price, renewalLabel, renewalDate) }),
1633
- paymentMethod ? /* @__PURE__ */ jsx(Text, { style: styles.meta, children: labels.paymentLine(paymentLabel, paymentMethod) }) : null
1634
- ] }),
1635
- actions.length > 0 ? /* @__PURE__ */ jsx(List, { children: actions.map((a) => /* @__PURE__ */ jsx(
1636
- ListRow,
1637
- {
1638
- title: a.label,
1639
- subtitle: a.value,
1640
- leading: a.icon ? /* @__PURE__ */ jsx(Icon, { name: a.icon, size: theme.icon.md, color: theme.color.text2 }) : null,
1641
- trailing: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: theme.icon.sm, color: theme.color.text3 }),
1642
- onPress: () => onAction?.(a.id)
1643
- },
1644
- a.id
1645
- )) }) : null,
1646
- onCancel ? /* @__PURE__ */ jsxs(Fragment, { children: [
1647
- /* @__PURE__ */ jsx(
1648
- Pressable,
1649
- {
1650
- accessibilityRole: "button",
1651
- accessibilityLabel: cancelLabel,
1652
- accessibilityState: { busy: cancelBusy },
1653
- onPress: cancelBusy ? void 0 : onCancel,
1654
- style: ({ pressed }) => [styles.cancel, pressed ? styles.cancelPressed : null],
1655
- children: /* @__PURE__ */ jsx(Text, { style: styles.cancelLabel, children: cancelLabel })
1656
- }
1657
- ),
1658
- cancelNote ? /* @__PURE__ */ jsx(Text, { style: styles.cancelNote, children: cancelNote }) : null
1659
- ] }) : null
1660
- ] });
1661
- }
1662
- var sheet7 = createStyleSheet((theme) => ({
1663
- screen: { flex: 1, backgroundColor: theme.color.bg },
1664
- scroll: { padding: theme.layout.screenPad, gap: theme.space.s3 },
1665
- card: {
1666
- padding: theme.space.s4,
1667
- borderRadius: theme.radius.lg,
1668
- backgroundColor: theme.color.surface,
1669
- borderWidth: theme.borderWidth.base,
1670
- borderColor: theme.color.border,
1671
- gap: theme.space.s2
1672
- },
1673
- cardHead: { flexDirection: "row", alignItems: "center", gap: theme.space.s2 },
1674
- planName: {
1675
- flexShrink: 1,
1676
- fontFamily: theme.font.sans,
1677
- fontWeight: theme.type.headline.fontWeight,
1678
- fontSize: theme.type.headline.fontSize,
1679
- lineHeight: theme.type.headline.lineHeight,
1680
- letterSpacing: theme.type.headline.letterSpacing,
1681
- color: theme.color.text
1682
- },
1683
- meta: {
1684
- fontFamily: theme.font.sans,
1685
- fontSize: theme.type.footnote.fontSize,
1686
- lineHeight: theme.type.footnote.lineHeight,
1687
- color: theme.color.text2
1688
- },
1689
- cancel: {
1690
- minHeight: theme.tapMin,
1691
- alignItems: "center",
1692
- justifyContent: "center",
1693
- borderRadius: theme.radius.md,
1694
- // Static `w2`: the destructive outline is the drawing, not chrome.
1695
- borderWidth: theme.borderWidth.thick,
1696
- borderColor: theme.color.danger,
1697
- backgroundColor: "transparent"
1698
- },
1699
- cancelPressed: { backgroundColor: theme.state.pressed },
1700
- // Text on a transparent surface, so the tone itself — not `dangerInk`, which
1701
- // belongs on a solid danger fill.
1702
- cancelLabel: {
1703
- fontFamily: theme.font.sans,
1704
- fontWeight: theme.fontWeight.bold,
1705
- fontSize: theme.type.callout.fontSize,
1706
- lineHeight: theme.type.callout.lineHeight,
1707
- color: theme.color.danger
1708
- },
1709
- cancelNote: {
1710
- fontFamily: theme.font.sans,
1711
- fontSize: theme.type.caption1.fontSize,
1712
- lineHeight: theme.type.caption1.fontSize * theme.lineHeight.normal,
1713
- color: theme.color.text3
1714
- },
1715
- // Badge hugs with `flex-start`, which pins it to the top of this centred row.
1716
- rowBadge: { alignSelf: "center" }
1717
- }));
1718
- function ToggleRow({
1719
- label,
1720
- description,
1721
- value,
1722
- onValueChange,
1723
- disabled = false,
1724
- style,
1725
- accessibilityLabel,
1726
- labels: labelsProp
1727
- }) {
1728
- const { styles } = useStyles(sheet8);
1729
- const labels = useLabels("toggleRow", TOGGLE_ROW_LABELS, labelsProp);
1730
- const announced = accessibilityLabel ?? (description ? labels.withDescription(label, description) : label);
1731
- return /* @__PURE__ */ jsxs(
1732
- Pressable,
1733
- {
1734
- accessibilityRole: "switch",
1735
- accessibilityLabel: announced,
1736
- accessibilityState: { checked: value, disabled },
1737
- "aria-checked": value,
1738
- disabled,
1739
- onPress: disabled ? void 0 : () => onValueChange?.(!value),
1740
- style: ({ pressed }) => [
1741
- styles.row,
1742
- disabled ? styles.disabled : null,
1743
- pressed && !disabled ? styles.pressed : null,
1744
- style
1745
- ],
1746
- children: [
1747
- /* @__PURE__ */ jsxs(View, { style: styles.main, children: [
1748
- /* @__PURE__ */ jsx(Text, { style: styles.label, children: label }),
1749
- description ? /* @__PURE__ */ jsx(Text, { style: styles.description, children: description }) : null
1750
- ] }),
1751
- /* @__PURE__ */ jsx(View, { "aria-hidden": true, style: styles.glyph, children: /* @__PURE__ */ jsx(Switch, { value, disabled, decorative: true }) })
1752
- ]
1753
- }
1754
- );
1755
- }
1756
- var sheet8 = createStyleSheet((theme) => ({
1757
- row: {
1758
- flexDirection: "row",
1759
- alignItems: "center",
1760
- gap: theme.space.s3,
1761
- minHeight: theme.tapMin,
1762
- paddingHorizontal: theme.space.s4,
1763
- paddingVertical: theme.space.s3,
1764
- backgroundColor: "transparent"
1765
- },
1766
- pressed: { backgroundColor: theme.state.pressed },
1767
- disabled: { opacity: theme.state.disabledOpacity },
1768
- main: { flex: 1, minWidth: 0, gap: theme.space.s1 },
1769
- label: {
1770
- fontFamily: theme.font.sans,
1771
- fontWeight: theme.type.headline.fontWeight,
1772
- fontSize: theme.type.headline.fontSize,
1773
- lineHeight: theme.type.headline.lineHeight,
1774
- letterSpacing: theme.type.headline.letterSpacing,
1775
- color: theme.color.text
1776
- },
1777
- description: {
1778
- fontFamily: theme.font.sans,
1779
- fontSize: theme.type.footnote.fontSize,
1780
- lineHeight: theme.type.footnote.lineHeight,
1781
- color: theme.color.text3
1782
- },
1783
- // `pointerEvents` in the style object, not as a prop: the prop form is
1784
- // deprecated in RN 0.76.
1785
- glyph: { flexShrink: 0, pointerEvents: "none" }
1786
- }));
1787
- function SettingsScreen({
1788
- groups,
1789
- onRowPress,
1790
- onToggle
1791
- }) {
1792
- const { styles } = useStyles(sheet9);
1793
- const theme = useLoamTheme("commerce");
1794
- return /* @__PURE__ */ jsx(ScrollView, { style: styles.screen, contentContainerStyle: styles.scroll, children: groups.map((group) => /* @__PURE__ */ jsxs(View, { style: styles.group, children: [
1795
- group.title ? /* @__PURE__ */ jsx(Text, { style: styles.caption, children: group.title }) : null,
1796
- /* @__PURE__ */ jsx(List, { children: group.rows.map((row) => {
1797
- if (row.kind === "switch") {
1798
- return /* @__PURE__ */ jsx(
1799
- ToggleRow,
1800
- {
1801
- label: row.label,
1802
- description: row.description,
1803
- value: row.value,
1804
- disabled: row.disabled,
1805
- onValueChange: (next) => {
1806
- row.onValueChange?.(next);
1807
- onToggle?.(row.id, next);
1808
- }
1809
- },
1810
- row.id
1811
- );
1812
- }
1813
- if (row.kind === "danger") {
1814
- return /* @__PURE__ */ jsx(
1815
- ListRow,
1816
- {
1817
- title: /* @__PURE__ */ jsx(Text, { style: styles.dangerLabel, children: row.label }),
1818
- accessibilityLabel: row.label,
1819
- onPress: () => {
1820
- row.onPress?.();
1821
- onRowPress?.(row.id);
1822
- }
1823
- },
1824
- row.id
1825
- );
1826
- }
1827
- return /* @__PURE__ */ jsx(
1828
- ListRow,
1829
- {
1830
- title: row.label,
1831
- accessibilityLabel: row.label,
1832
- leading: row.icon ? /* @__PURE__ */ jsx(Icon, { name: row.icon, size: theme.icon.md, color: theme.color.text2 }) : null,
1833
- trailing: /* @__PURE__ */ jsxs(View, { style: styles.trailing, children: [
1834
- row.value ? /* @__PURE__ */ jsx(Text, { style: styles.value, children: row.value }) : null,
1835
- /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: theme.icon.sm, color: theme.color.text3 })
1836
- ] }),
1837
- onPress: () => {
1838
- row.onPress?.();
1839
- onRowPress?.(row.id);
1840
- }
1841
- },
1842
- row.id
1843
- );
1844
- }) }),
1845
- group.footnote ? /* @__PURE__ */ jsx(Text, { style: styles.footnote, children: group.footnote }) : null
1846
- ] }, group.id)) });
1847
- }
1848
- var sheet9 = createStyleSheet((theme) => ({
1849
- screen: { flex: 1, backgroundColor: theme.color.bg },
1850
- scroll: { padding: theme.layout.screenPad, gap: theme.space.s5 },
1851
- group: { gap: theme.space.s2 },
1852
- // Uppercase group caption. `tracking.caps` is an em multiple, so it is
1853
- // multiplied by the font size to become RN's absolute letterSpacing.
1854
- caption: {
1855
- paddingStart: theme.space.s1,
1856
- fontFamily: theme.font.sans,
1857
- fontWeight: theme.fontWeight.bold,
1858
- fontSize: theme.type.caption2.fontSize,
1859
- lineHeight: theme.type.caption2.lineHeight,
1860
- letterSpacing: theme.type.caption2.fontSize * theme.tracking.caps,
1861
- textTransform: "uppercase",
1862
- color: theme.color.text3
1863
- },
1864
- trailing: { flexDirection: "row", alignItems: "center", gap: theme.space.s1 },
1865
- value: {
1866
- fontFamily: theme.font.sans,
1867
- fontSize: theme.type.footnote.fontSize,
1868
- lineHeight: theme.type.footnote.lineHeight,
1869
- color: theme.color.text3
1870
- },
1871
- // Destructive rows are the tone itself on a surface — `dangerInk` belongs on a
1872
- // solid danger fill, not on a list row.
1873
- dangerLabel: {
1874
- fontFamily: theme.font.sans,
1875
- fontWeight: theme.type.headline.fontWeight,
1876
- fontSize: theme.type.headline.fontSize,
1877
- lineHeight: theme.type.headline.lineHeight,
1878
- letterSpacing: theme.type.headline.letterSpacing,
1879
- color: theme.color.danger
1880
- },
1881
- footnote: {
1882
- paddingStart: theme.space.s1,
1883
- fontFamily: theme.font.sans,
1884
- fontSize: theme.type.caption1.fontSize,
1885
- lineHeight: theme.type.caption1.fontSize * theme.lineHeight.normal,
1886
- color: theme.color.text3
1887
- }
1888
- }));
1889
- function NotificationPreferences({
1890
- systemEnabled = true,
1891
- systemNote,
1892
- systemActionLabel: systemActionLabelProp,
1893
- onOpenSystemSettings,
1894
- categories,
1895
- onChange,
1896
- labels: labelsProp
1897
- }) {
1898
- const { styles } = useStyles(sheet10);
1899
- const labels = useLabels("notificationPreferences", NOTIFICATION_PREFERENCES_LABELS, labelsProp);
1900
- const systemActionLabel = systemActionLabelProp ?? labels.openSettings;
1901
- const note = systemNote ?? (systemEnabled ? labels.systemOn : labels.systemOff);
1902
- return /* @__PURE__ */ jsxs(ScrollView, { style: styles.screen, contentContainerStyle: styles.scroll, children: [
1903
- /* @__PURE__ */ jsxs(
1904
- View,
1905
- {
1906
- accessibilityRole: systemEnabled ? "text" : "alert",
1907
- style: [styles.banner, systemEnabled ? styles.bannerOn : styles.bannerOff],
1908
- children: [
1909
- /* @__PURE__ */ jsx(
1910
- Text,
1911
- {
1912
- style: [styles.bannerText, systemEnabled ? styles.bannerTextOn : styles.bannerTextOff],
1913
- children: note
1914
- }
1915
- ),
1916
- !systemEnabled && onOpenSystemSettings ? /* @__PURE__ */ jsx(
1917
- Pressable,
1918
- {
1919
- accessibilityRole: "button",
1920
- accessibilityLabel: systemActionLabel,
1921
- onPress: onOpenSystemSettings,
1922
- style: ({ pressed }) => [styles.bannerAction, pressed ? styles.pressed : null],
1923
- children: /* @__PURE__ */ jsx(Text, { style: styles.bannerActionLabel, children: systemActionLabel })
1924
- }
1925
- ) : null
1926
- ]
1927
- }
1928
- ),
1929
- categories.map((c) => /* @__PURE__ */ jsx(
1930
- ToggleRow,
1931
- {
1932
- label: c.label,
1933
- description: c.description,
1934
- value: c.value,
1935
- disabled: c.disabled === true || !systemEnabled,
1936
- onValueChange: (next) => onChange?.(c.id, next),
1937
- style: styles.card
1938
- },
1939
- c.id
1940
- ))
1941
- ] });
1942
- }
1943
- var sheet10 = createStyleSheet((theme) => ({
1944
- screen: { flex: 1, backgroundColor: theme.color.bg },
1945
- scroll: { padding: theme.layout.screenPad, gap: theme.space.s3 },
1946
- banner: {
1947
- padding: theme.space.s4,
1948
- borderRadius: theme.radius.lg,
1949
- borderWidth: theme.borderWidth.base,
1950
- gap: theme.space.s3,
1951
- alignItems: "flex-start"
1952
- },
1953
- bannerOn: { backgroundColor: theme.color.accentSoft, borderColor: theme.edge.accent },
1954
- bannerOff: { backgroundColor: theme.color.warnSoft, borderColor: theme.edge.warn },
1955
- bannerText: {
1956
- fontFamily: theme.font.sans,
1957
- fontSize: theme.type.footnote.fontSize,
1958
- lineHeight: theme.type.footnote.fontSize * theme.lineHeight.normal
1959
- },
1960
- // Text on a `-soft` tint is a surface case: the tone itself, never the on-ink.
1961
- bannerTextOn: { color: theme.color.accentOnSoft },
1962
- bannerTextOff: { color: theme.color.warnOnSoft },
1963
- bannerAction: {
1964
- minHeight: theme.tapMin,
1965
- justifyContent: "center",
1966
- paddingHorizontal: theme.space.s3,
1967
- borderRadius: theme.radius.md,
1968
- backgroundColor: theme.color.warn
1969
- },
1970
- // Solid `warn` fill, so the measured ink for that fill.
1971
- bannerActionLabel: {
1972
- fontFamily: theme.font.sans,
1973
- fontWeight: theme.fontWeight.bold,
1974
- fontSize: theme.type.footnote.fontSize,
1975
- color: theme.color.warnInk
1976
- },
1977
- pressed: { opacity: theme.state.pressedOpacity },
1978
- card: {
1979
- borderRadius: theme.radius.lg,
1980
- backgroundColor: theme.color.surface,
1981
- borderWidth: theme.borderWidth.base,
1982
- borderColor: theme.color.border
1983
- }
1984
- }));
1985
-
1986
- export { BillingPeriodToggle, DeleteAccountScreen, ManageSubscription, MeterBar, NotificationPreferences, Paywall, PaywallGate, PaywallSurface, PlanCard, PlanFeatureRow, PlanGrid, PlanPriceCell, PlanPriceDelta, ProrationLine, ProrationTable, SavingsChip, SettingsScreen, ToggleRow };