@btndprojects/loam-ui-native 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/README.md +56 -0
  2. package/dist/accordion/index.js +5 -3
  3. package/dist/adaptive/index.js +6 -2
  4. package/dist/alert/index.js +5 -2
  5. package/dist/analyzer/index.js +9 -6
  6. package/dist/announcement/index.js +8 -5
  7. package/dist/audio-player/index.js +5 -3
  8. package/dist/avatar/index.js +5 -2
  9. package/dist/avatar-group/index.js +7 -3
  10. package/dist/badge/index.js +7 -4
  11. package/dist/banner/index.js +5 -2
  12. package/dist/board/index.js +11 -6
  13. package/dist/button/index.js +6 -3
  14. package/dist/camera-permission/index.js +15 -12
  15. package/dist/capture-result/index.js +19 -16
  16. package/dist/card/index.js +6 -3
  17. package/dist/card-form/index.js +12 -8
  18. package/dist/carousel/index.js +4 -2
  19. package/dist/chart/index.js +8 -5
  20. package/dist/charts/index.js +8 -6
  21. package/dist/chat/index.js +16 -0
  22. package/dist/checkbox/index.js +6 -4
  23. package/dist/checklist/index.js +11 -8
  24. package/dist/checkout/index.js +16 -11
  25. package/dist/chip/index.js +7 -4
  26. package/dist/{chunk-XNUVB5OL.js → chunk-2OLKPG4E.js} +92 -28
  27. package/dist/{chunk-RUZHTGKB.js → chunk-2PKYGLQ6.js} +71 -40
  28. package/dist/{chunk-UC2WGUP3.js → chunk-2SWKL3AJ.js} +91 -252
  29. package/dist/{chunk-AI4DWZCD.js → chunk-2SY63FCH.js} +63 -16
  30. package/dist/{chunk-F5XNPWS7.js → chunk-2TXERVVA.js} +92 -35
  31. package/dist/chunk-36EC2T6P.js +581 -0
  32. package/dist/chunk-3DUWIYV5.js +437 -0
  33. package/dist/{chunk-RGQWWKLA.js → chunk-3QMEOFW5.js} +275 -71
  34. package/dist/chunk-3WEZCGHX.js +265 -0
  35. package/dist/chunk-46MMSDGL.js +194 -0
  36. package/dist/{chunk-7O2FMUPT.js → chunk-4IZXHVFJ.js} +297 -92
  37. package/dist/{chunk-LAECSR4H.js → chunk-5LAAAXFP.js} +14 -8
  38. package/dist/{chunk-2A5NIQAK.js → chunk-5RENVKBQ.js} +134 -46
  39. package/dist/{chunk-2ZZ7TDJ4.js → chunk-5UTRIXQ6.js} +37 -31
  40. package/dist/{chunk-LOE5YNN3.js → chunk-5VFZRGVD.js} +37 -10
  41. package/dist/{chunk-52X2VYTD.js → chunk-67IZZ2MJ.js} +115 -60
  42. package/dist/{chunk-UYG5L34B.js → chunk-6YAQBXB3.js} +10 -4
  43. package/dist/{chunk-BTTFCMKG.js → chunk-74FLKD24.js} +94 -23
  44. package/dist/{chunk-ITTYJZWX.js → chunk-7BUIKDD6.js} +73 -18
  45. package/dist/{chunk-FOKG57CR.js → chunk-7OVVSVEZ.js} +273 -109
  46. package/dist/chunk-AEB7KCHQ.js +287 -0
  47. package/dist/chunk-APCWFOZW.js +28 -0
  48. package/dist/chunk-AWKQIE5I.js +139 -0
  49. package/dist/{chunk-VCDBXW5H.js → chunk-B7N4ASYE.js} +86 -42
  50. package/dist/{chunk-IVNRBPGC.js → chunk-C4GTDLRC.js} +104 -20
  51. package/dist/{chunk-4ZAHCY44.js → chunk-C6APNDVA.js} +12 -5
  52. package/dist/{chunk-4SZYY6AN.js → chunk-CMTVNF3D.js} +18 -13
  53. package/dist/{chunk-WVKKJA6U.js → chunk-CPTOADB2.js} +151 -96
  54. package/dist/chunk-D5N5QWI7.js +1325 -0
  55. package/dist/{chunk-IIQTAY3J.js → chunk-DN7MNQIP.js} +113 -29
  56. package/dist/{chunk-47FWHGUN.js → chunk-DVGBZ3TX.js} +84 -23
  57. package/dist/chunk-DW3L54DQ.js +305 -0
  58. package/dist/{chunk-3ARE4TES.js → chunk-E2E3I5W2.js} +69 -18
  59. package/dist/{chunk-DHWADYZX.js → chunk-EDCBJV7J.js} +41 -28
  60. package/dist/{chunk-WSW6ZFAQ.js → chunk-ENP3BMZU.js} +4 -4
  61. package/dist/{chunk-OOPPQH27.js → chunk-EVOIGUBI.js} +43 -19
  62. package/dist/{chunk-VEAYTRPX.js → chunk-EY4DD67D.js} +165 -97
  63. package/dist/{chunk-223Q2T2Q.js → chunk-F3H33DQX.js} +132 -61
  64. package/dist/{chunk-CYRBHQQZ.js → chunk-F5B3UINI.js} +68 -35
  65. package/dist/{chunk-6X6PQ443.js → chunk-FAJI7BSC.js} +20 -9
  66. package/dist/{chunk-MOUJOP55.js → chunk-FUMHAAF3.js} +96 -29
  67. package/dist/{chunk-6HT2LP62.js → chunk-FV6HMP7W.js} +192 -73
  68. package/dist/{chunk-S7F6XLTK.js → chunk-FYWNRX4F.js} +76 -47
  69. package/dist/{chunk-YG3ZJHGU.js → chunk-FZGAAOKS.js} +30 -8
  70. package/dist/{chunk-YDGVJETP.js → chunk-G3AFC24V.js} +1 -1
  71. package/dist/{chunk-EJBDRVIH.js → chunk-G6UESEVN.js} +15 -8
  72. package/dist/chunk-GDKVKNR2.js +339 -0
  73. package/dist/chunk-GEIGMWNF.js +10 -0
  74. package/dist/{chunk-JUAMLEHX.js → chunk-H7DWSL4O.js} +24 -12
  75. package/dist/chunk-HJFFOOJ4.js +1 -0
  76. package/dist/{chunk-RW6ZL2FQ.js → chunk-HJLPZA4X.js} +106 -21
  77. package/dist/chunk-HYEOQWT7.js +647 -0
  78. package/dist/chunk-I2KLQ2HA.js +19 -0
  79. package/dist/{chunk-CJ5EOYZE.js → chunk-I4FHVKEC.js} +11 -5
  80. package/dist/{chunk-JNH2TYIN.js → chunk-IDM7JJMO.js} +19 -5
  81. package/dist/{chunk-O4AEHWII.js → chunk-IPUNJMAQ.js} +141 -49
  82. package/dist/{chunk-J7Q7VCVC.js → chunk-IT6FUXXG.js} +13 -6
  83. package/dist/{chunk-QJJ6MADV.js → chunk-IVKMZ7BB.js} +80 -28
  84. package/dist/{chunk-Z7H7VSFZ.js → chunk-IXKWIFWZ.js} +17 -6
  85. package/dist/chunk-J64KGCGX.js +55 -0
  86. package/dist/chunk-JBMLWFSJ.js +270 -0
  87. package/dist/{chunk-4BXMXBJO.js → chunk-JJLPBRVZ.js} +22 -11
  88. package/dist/chunk-JLC6PM5S.js +406 -0
  89. package/dist/chunk-JUYWSSKW.js +335 -0
  90. package/dist/{chunk-7CFF4HXS.js → chunk-JV5YOTOB.js} +49 -11
  91. package/dist/{chunk-LZLHELAG.js → chunk-KFJGFLMW.js} +29 -8
  92. package/dist/{chunk-O7AE6DAF.js → chunk-KQZ3GLHR.js} +18 -8
  93. package/dist/{chunk-N32RGOA5.js → chunk-LKFC4CS7.js} +80 -24
  94. package/dist/{chunk-YC6WORFL.js → chunk-LMPHCVJJ.js} +82 -50
  95. package/dist/{chunk-3WPW4KUN.js → chunk-LQP4KEXZ.js} +45 -13
  96. package/dist/{chunk-TKQYWZ5V.js → chunk-LUMVGO2K.js} +47 -31
  97. package/dist/{chunk-AWJOCGFZ.js → chunk-M656FYNH.js} +25 -13
  98. package/dist/{chunk-35OFI3JG.js → chunk-MKSNFG7H.js} +73 -20
  99. package/dist/{chunk-4GBOGOTV.js → chunk-NBEF4EPJ.js} +16 -6
  100. package/dist/chunk-NNCOFLNE.js +24 -0
  101. package/dist/{chunk-4YQOR7JM.js → chunk-NTQ2F3AU.js} +73 -20
  102. package/dist/{chunk-QCDXZBC5.js → chunk-O5V4TG3V.js} +126 -44
  103. package/dist/{chunk-U7TFM2JA.js → chunk-OJQUBQWA.js} +3 -3
  104. package/dist/{chunk-VQHPQEUH.js → chunk-OWAMM2DK.js} +13 -6
  105. package/dist/chunk-PID3NJB7.js +405 -0
  106. package/dist/{chunk-66SG2H23.js → chunk-PMMTGBBS.js} +27 -17
  107. package/dist/{chunk-RIBDXGUG.js → chunk-PNF3NKB5.js} +49 -16
  108. package/dist/{chunk-JXJB2X6M.js → chunk-Q6NKEPRE.js} +81 -32
  109. package/dist/chunk-QDZGFXQD.js +176 -0
  110. package/dist/{chunk-SYNOJOQO.js → chunk-QEYFDRHR.js} +60 -26
  111. package/dist/{chunk-VBOXAEPI.js → chunk-QHAITQIF.js} +97 -22
  112. package/dist/{chunk-VXDZFJGP.js → chunk-QHTVYA65.js} +230 -76
  113. package/dist/{chunk-TUTI5HOZ.js → chunk-QIKT7LIB.js} +14 -8
  114. package/dist/{chunk-3ENTMPQY.js → chunk-QP3KMOVF.js} +82 -42
  115. package/dist/{chunk-GNNJ4GCC.js → chunk-QPWDDJJ4.js} +62 -148
  116. package/dist/{chunk-QWCMU5B2.js → chunk-QRUMA22E.js} +205 -80
  117. package/dist/{chunk-ZVFE5QGU.js → chunk-QYPE5JX3.js} +50 -10
  118. package/dist/{chunk-PUPM2YGF.js → chunk-ROCUG24E.js} +76 -36
  119. package/dist/{chunk-NQYBUO3K.js → chunk-RU3ZPNL6.js} +333 -142
  120. package/dist/{chunk-TOXAGRDQ.js → chunk-RXSCIO6W.js} +14 -5
  121. package/dist/{chunk-FIF2M24N.js → chunk-SATMR6SG.js} +631 -203
  122. package/dist/{chunk-4YIP3CWS.js → chunk-SHHY5OMK.js} +7 -5
  123. package/dist/chunk-SKWO3SZF.js +2284 -0
  124. package/dist/{chunk-YF4NSSMT.js → chunk-SWS5JQIF.js} +41 -13
  125. package/dist/{chunk-CUMUNPXY.js → chunk-T5LTPKX6.js} +15 -7
  126. package/dist/{chunk-H6NIOQHK.js → chunk-TDMG26JI.js} +26 -6
  127. package/dist/{chunk-UWFLYMAR.js → chunk-TLCIR6RG.js} +267 -126
  128. package/dist/{chunk-SBMNWWBV.js → chunk-TN2ZNJUI.js} +47 -9
  129. package/dist/{chunk-5YNTNN5A.js → chunk-TQVAIKFD.js} +106 -41
  130. package/dist/chunk-TRGFFU6A.js +1456 -0
  131. package/dist/{chunk-2GK6PHGE.js → chunk-TY4MTKQJ.js} +100 -22
  132. package/dist/{chunk-AZRX6SAC.js → chunk-U23FYWME.js} +15 -7
  133. package/dist/{chunk-PZXZJBMP.js → chunk-U5NLHYV6.js} +26 -12
  134. package/dist/chunk-UQEN55EY.js +1 -0
  135. package/dist/chunk-UQGBTPXH.js +218 -0
  136. package/dist/chunk-UXGIW7OK.js +116 -0
  137. package/dist/{chunk-PJXUJYS6.js → chunk-UYGDJWMN.js} +55 -30
  138. package/dist/{chunk-QDYDBCFP.js → chunk-V2OEB75Z.js} +50 -51
  139. package/dist/{chunk-LSS54GLJ.js → chunk-VAOAKWUK.js} +34 -13
  140. package/dist/{chunk-DM5QUKKO.js → chunk-VDPK5CY4.js} +18 -6
  141. package/dist/chunk-W23G6JLF.js +37 -0
  142. package/dist/{chunk-CDRZHT42.js → chunk-W63AJTM7.js} +276 -12
  143. package/dist/{chunk-XXXEFXY5.js → chunk-W74TXYFB.js} +13 -5
  144. package/dist/{chunk-LRJNDEIA.js → chunk-WRDSPUE7.js} +144 -29
  145. package/dist/{chunk-C2NTXVWM.js → chunk-XBZGDDMR.js} +11 -4
  146. package/dist/{chunk-BV3B2HYZ.js → chunk-XIDTBCBA.js} +189 -131
  147. package/dist/{chunk-DSJBXLUG.js → chunk-XN4KG3P4.js} +348 -153
  148. package/dist/chunk-XQXMLMH3.js +211 -0
  149. package/dist/{chunk-HPPW424V.js → chunk-XTORZWRF.js} +19 -8
  150. package/dist/{chunk-P23EQNRQ.js → chunk-YAAHPATV.js} +181 -30
  151. package/dist/{chunk-KMI5ML5I.js → chunk-YXOAPXMU.js} +57 -18
  152. package/dist/{chunk-RJQOOHT2.js → chunk-ZECZOOSB.js} +59 -28
  153. package/dist/{chunk-QKXCPTFS.js → chunk-ZLTO5VQI.js} +121 -31
  154. package/dist/{chunk-BEDBFJND.js → chunk-ZVATDZOM.js} +16 -18
  155. package/dist/coachmark/index.js +6 -3
  156. package/dist/code-block/index.js +5 -3
  157. package/dist/color-field/index.js +6 -4
  158. package/dist/commerce/index.js +19 -16
  159. package/dist/connectivity/index.js +5 -2
  160. package/dist/context-menu/index.js +5 -3
  161. package/dist/copy-button/index.js +4 -2
  162. package/dist/data-grid/index.js +21 -16
  163. package/dist/date-range-picker/index.js +11 -8
  164. package/dist/description-list/index.js +3 -1
  165. package/dist/dialog/index.js +4 -2
  166. package/dist/empty-state/index.js +4 -2
  167. package/dist/error-summary/index.js +4 -2
  168. package/dist/fab/index.js +5 -2
  169. package/dist/file-manager/index.js +28 -0
  170. package/dist/file-upload/index.js +10 -7
  171. package/dist/filter-bar/index.js +9 -6
  172. package/dist/flow-run/index.js +15 -12
  173. package/dist/form/index.js +5 -3
  174. package/dist/gallery/index.js +5 -2
  175. package/dist/hold-to-confirm/index.js +4 -2
  176. package/dist/index.d.ts +9557 -2985
  177. package/dist/index.js +355 -122
  178. package/dist/infinite-list/index.js +4 -2
  179. package/dist/inline-edit/index.js +6 -4
  180. package/dist/input/index.js +5 -3
  181. package/dist/interactions/index.js +2 -1
  182. package/dist/invoice/index.js +13 -9
  183. package/dist/kbd/index.js +5 -1
  184. package/dist/keyboard/index.js +4 -2
  185. package/dist/list-row/index.js +6 -4
  186. package/dist/log-viewer/index.js +4 -2
  187. package/dist/map-view/index.js +5 -3
  188. package/dist/markdown/index.js +9 -6
  189. package/dist/metric/index.js +7 -4
  190. package/dist/money/index.js +9 -3
  191. package/dist/nav-drawer/index.js +4 -2
  192. package/dist/nav-header/index.js +9 -0
  193. package/dist/navigation/index.js +5 -2
  194. package/dist/notification-center/index.js +12 -10
  195. package/dist/number-roll/index.js +5 -2
  196. package/dist/one-handed/index.js +5 -3
  197. package/dist/os-surfaces/index.js +6 -3
  198. package/dist/otp/index.js +7 -4
  199. package/dist/page-header/index.js +1 -0
  200. package/dist/pagination/index.js +6 -0
  201. package/dist/payment-method/index.js +14 -10
  202. package/dist/payment-status/index.js +17 -14
  203. package/dist/permission/index.js +5 -2
  204. package/dist/picker/index.js +11 -6
  205. package/dist/progress/index.js +6 -3
  206. package/dist/pull-to-refresh/index.js +4 -2
  207. package/dist/radio-group/index.js +6 -4
  208. package/dist/rating/index.js +5 -2
  209. package/dist/receivables/index.js +21 -16
  210. package/dist/refund/index.js +18 -14
  211. package/dist/save-status/index.js +5 -3
  212. package/dist/scroll-area/index.js +3 -1
  213. package/dist/search-field/index.js +8 -0
  214. package/dist/segmented-control/index.js +4 -3
  215. package/dist/sheet/index.js +5 -3
  216. package/dist/skeleton/index.js +3 -1
  217. package/dist/slider/index.js +4 -2
  218. package/dist/sortable/index.js +7 -0
  219. package/dist/spinner/index.js +3 -1
  220. package/dist/split-button/index.js +9 -6
  221. package/dist/spotlight/index.js +3 -1
  222. package/dist/stage-timeline/index.js +5 -3
  223. package/dist/status-dot/index.js +4 -2
  224. package/dist/stepper/index.js +7 -4
  225. package/dist/streaming-text/index.js +3 -2
  226. package/dist/survey/index.js +18 -15
  227. package/dist/switch/index.js +5 -3
  228. package/dist/system-state/index.js +7 -4
  229. package/dist/tab-bar/index.js +5 -2
  230. package/dist/tabs/index.js +4 -2
  231. package/dist/tags-input/index.js +10 -0
  232. package/dist/textarea/index.js +6 -4
  233. package/dist/thinking/index.js +3 -1
  234. package/dist/time-field/index.js +12 -0
  235. package/dist/time-range-control/index.js +22 -0
  236. package/dist/timeline/index.js +4 -2
  237. package/dist/toast/index.js +4 -2
  238. package/dist/toolbar/index.js +4 -2
  239. package/dist/tour/index.js +12 -9
  240. package/dist/truncation-notice/index.js +5 -2
  241. package/dist/update-notice/index.js +12 -9
  242. package/dist/video-player/index.js +5 -2
  243. package/dist/viewfinder/index.js +6 -4
  244. package/dist/widget/index.js +7 -4
  245. package/dist/wizard/index.js +7 -4
  246. package/package.json +13 -12
  247. package/dist/chunk-6N33LFQA.js +0 -35
  248. package/dist/chunk-GDKZTW34.js +0 -395
  249. package/dist/chunk-GL7B2DOW.js +0 -134
  250. package/dist/chunk-NKB7BZYK.js +0 -167
  251. package/dist/chunk-OETCUXQP.js +0 -134
  252. package/dist/chunk-OPXFZ4Y5.js +0 -204
  253. package/dist/chunk-Q72LJOVE.js +0 -169
  254. package/dist/chunk-RNGLIHFA.js +0 -191
  255. package/dist/chunk-RQ3HASCC.js +0 -6
  256. package/dist/chunk-RSOJT5YW.js +0 -124
  257. package/dist/chunk-TKVFVF5D.js +0 -95
  258. package/dist/chunk-XOSCY2CW.js +0 -242
  259. package/dist/header/index.js +0 -5
  260. package/dist/search-bar/index.js +0 -5
  261. /package/dist/{chunk-3ECPOSKO.js → chunk-3UG6JUCV.js} +0 -0
  262. /package/dist/{chunk-JRLTGLN4.js → chunk-5WWRTEPS.js} +0 -0
  263. /package/dist/{chunk-RTIKSY6A.js → chunk-5Z5ZYMOJ.js} +0 -0
@@ -1,16 +1,20 @@
1
- import { Spinner } from './chunk-O7AE6DAF.js';
1
+ import { Spinner } from './chunk-KQZ3GLHR.js';
2
+ import { useLabels } from './chunk-APCWFOZW.js';
2
3
  import * as React from 'react';
3
4
  import { FlatList, View } from 'react-native';
4
5
  import { createStyleSheet, useStyles } from '@btndprojects/loam-theme-native';
5
6
  import { jsx, Fragment } from 'react/jsx-runtime';
6
7
 
8
+ var DEFAULT_LABELS = {
9
+ loadingMore: "Loading more"
10
+ };
7
11
  function loadMoreIfNeeded(opts) {
8
12
  if (opts.hasMore && !opts.loading) opts.onLoadMore();
9
13
  }
10
14
  var FOOTER_SPINNER_SIZE = "lg";
11
- function Footer() {
15
+ function Footer({ label }) {
12
16
  const { styles } = useStyles(sheet);
13
- return /* @__PURE__ */ jsx(View, { style: styles.footer, children: /* @__PURE__ */ jsx(Spinner, { size: FOOTER_SPINNER_SIZE, accessibilityLabel: "Loading more" }) });
17
+ return /* @__PURE__ */ jsx(View, { style: styles.footer, children: /* @__PURE__ */ jsx(Spinner, { size: FOOTER_SPINNER_SIZE, accessibilityLabel: label }) });
14
18
  }
15
19
  function InfiniteList({
16
20
  data,
@@ -23,9 +27,11 @@ function InfiniteList({
23
27
  // Accepted for API parity but intentionally inert — a virtualized list must
24
28
  // not animate (recycled rows would flicker). Destructured so it is never
25
29
  // forwarded onto the underlying FlatList.
26
- motion: _motion = "full"
30
+ motion: _motion = "full",
31
+ labels: labelsProp
27
32
  }) {
28
33
  const { styles } = useStyles(sheet);
34
+ const labels = useLabels("infiniteList", DEFAULT_LABELS, labelsProp);
29
35
  const handleEndReached = React.useCallback(() => {
30
36
  loadMoreIfNeeded({ hasMore, loading, onLoadMore });
31
37
  }, [hasMore, loading, onLoadMore]);
@@ -43,7 +49,7 @@ function InfiniteList({
43
49
  onEndReached: handleEndReached,
44
50
  onEndReachedThreshold,
45
51
  contentContainerStyle: styles.content,
46
- ListFooterComponent: loading ? /* @__PURE__ */ jsx(Footer, {}) : null
52
+ ListFooterComponent: loading ? /* @__PURE__ */ jsx(Footer, { label: labels.loadingMore }) : null
47
53
  }
48
54
  );
49
55
  }
@@ -1,19 +1,25 @@
1
- import { Icon } from './chunk-TKVFVF5D.js';
1
+ import { useLabels } from './chunk-APCWFOZW.js';
2
+ import { Icon } from './chunk-UXGIW7OK.js';
2
3
  import 'react';
3
4
  import { ScrollView, Pressable, View } from 'react-native';
4
5
  import { createStyleSheet, useStyles, useLoamTheme } from '@btndprojects/loam-theme-native';
5
6
  import { jsxs, jsx } from 'react/jsx-runtime';
6
7
 
8
+ var DEFAULT_LABELS = {
9
+ more: "More"
10
+ };
7
11
  function Toolbar({
8
12
  children,
9
13
  accessibilityLabel,
10
14
  overflow = "wrap",
11
15
  density = "comfortable",
12
16
  justify = "start",
13
- onMorePress
17
+ onMorePress,
18
+ labels: labelsProp
14
19
  }) {
20
+ const labels = useLabels("toolbar", DEFAULT_LABELS, labelsProp);
15
21
  const { styles } = useStyles(sheet, { density, justify });
16
- const theme = useLoamTheme();
22
+ const theme = useLoamTheme("toolbar");
17
23
  if (overflow === "scroll" || overflow === "menu") {
18
24
  return /* @__PURE__ */ jsxs(
19
25
  ScrollView,
@@ -30,7 +36,7 @@ function Toolbar({
30
36
  Pressable,
31
37
  {
32
38
  accessibilityRole: "button",
33
- accessibilityLabel: "More",
39
+ accessibilityLabel: labels.more,
34
40
  onPress: onMorePress,
35
41
  hitSlop: 8,
36
42
  style: styles.more,
@@ -41,7 +47,15 @@ function Toolbar({
41
47
  }
42
48
  );
43
49
  }
44
- return /* @__PURE__ */ jsx(View, { accessibilityRole: "toolbar", accessibilityLabel, style: styles.wrapRoot, children });
50
+ return /* @__PURE__ */ jsx(
51
+ View,
52
+ {
53
+ accessibilityRole: "toolbar",
54
+ accessibilityLabel,
55
+ style: styles.wrapRoot,
56
+ children
57
+ }
58
+ );
45
59
  }
46
60
  var sheet = createStyleSheet((theme) => ({
47
61
  // A wrapping row. `toolbarH` sets the resting height of a single-line strip;
@@ -1,16 +1,73 @@
1
- import { CardBrandMark } from './chunk-PUPM2YGF.js';
2
- import { Checkbox } from './chunk-JXJB2X6M.js';
3
- import { TextField, useColorTransition } from './chunk-ITTYJZWX.js';
1
+ import { CardBrandMark } from './chunk-ROCUG24E.js';
2
+ import { usePayLabels } from './chunk-GEIGMWNF.js';
3
+ import { Checkbox } from './chunk-Q6NKEPRE.js';
4
+ import { TextField, useColorTransition } from './chunk-7BUIKDD6.js';
4
5
  import { NO_UA_FOCUS_RING } from './chunk-3NMD74ZU.js';
5
- import { useResolvedMotion } from './chunk-6N33LFQA.js';
6
- import { Icon } from './chunk-TKVFVF5D.js';
6
+ import { useLabels } from './chunk-APCWFOZW.js';
7
+ import { Icon } from './chunk-UXGIW7OK.js';
8
+ import { useResolvedMotion, springConfig } from './chunk-J64KGCGX.js';
7
9
  import * as React from 'react';
8
10
  import { Text, useWindowDimensions, View, Easing, Animated, TextInput } from 'react-native';
9
11
  import { createStyleSheet, useStyles, useLoamTheme } from '@btndprojects/loam-theme-native';
10
- import { formatCard, formatExpiry, validCardNumber, CARD_COPY, validExpiry, validCvc } from '@btndprojects/loam-pay';
11
- import { jsx, jsxs } from 'react/jsx-runtime';
12
+ import { formatCard, formatExpiry, validCardNumber, resolvePayLabels, validExpiry, validCvc } from '@btndprojects/loam-pay';
13
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
12
14
 
13
- var TEST_HINT = "Test with 4242 4242 4242 4242 \xB7 12/34 \xB7 any code";
15
+ // src/card-form/card-form-labels.ts
16
+ var DEFAULT_LABELS = {
17
+ cardNumber: "Card number",
18
+ expiry: "Expiry",
19
+ expiryHint: "MM/YY",
20
+ securityCode: "Security code",
21
+ nameOnCard: "Name on card",
22
+ saveCard: "Save this card for next time",
23
+ testHint: "Test with 4242 4242 4242 4242 \xB7 12/34 \xB7 any code",
24
+ valid: "Valid",
25
+ numberPlaceholder: "1234 5678 9012 3456"
26
+ };
27
+ function BrandSwap({ brand }) {
28
+ const theme = useLoamTheme("card-form");
29
+ const [shown, setShown] = React.useState({
30
+ cur: brand,
31
+ prev: null
32
+ });
33
+ if (shown.cur !== brand) setShown({ cur: brand, prev: shown.cur });
34
+ const t = React.useRef(new Animated.Value(1)).current;
35
+ React.useEffect(() => {
36
+ if (!shown.prev) return;
37
+ t.setValue(0);
38
+ const done = () => setShown((s) => ({ ...s, prev: null }));
39
+ if (theme.reduceMotion) {
40
+ Animated.timing(t, { toValue: 1, duration: theme.duration.fast, useNativeDriver: true }).start(done);
41
+ } else {
42
+ Animated.spring(t, { ...springConfig(theme, "fs"), toValue: 1, useNativeDriver: true }).start(done);
43
+ }
44
+ }, [shown.prev, t, theme]);
45
+ const rise = theme.reduceMotion ? 0 : 6;
46
+ return /* @__PURE__ */ jsxs(View, { children: [
47
+ shown.prev ? /* @__PURE__ */ jsx(
48
+ Animated.View,
49
+ {
50
+ pointerEvents: "none",
51
+ style: {
52
+ position: "absolute",
53
+ opacity: t.interpolate({ inputRange: [0, 1], outputRange: [1, 0], extrapolate: "clamp" }),
54
+ transform: [{ translateY: t.interpolate({ inputRange: [0, 1], outputRange: [0, -rise] }) }]
55
+ },
56
+ children: /* @__PURE__ */ jsx(CardBrandMark, { brand: shown.prev })
57
+ }
58
+ ) : null,
59
+ /* @__PURE__ */ jsx(
60
+ Animated.View,
61
+ {
62
+ style: {
63
+ opacity: shown.prev ? t.interpolate({ inputRange: [0, 1], outputRange: [0, 1], extrapolate: "clamp" }) : 1,
64
+ transform: [{ translateY: t.interpolate({ inputRange: [0, 1], outputRange: [rise, 0] }) }]
65
+ },
66
+ children: /* @__PURE__ */ jsx(CardBrandMark, { brand: shown.cur })
67
+ }
68
+ )
69
+ ] });
70
+ }
14
71
  var CardRunContext = React.createContext(null);
15
72
  function onlyDigits(text) {
16
73
  return String(text).replace(/\D/g, "");
@@ -40,14 +97,17 @@ function DigitsField({
40
97
  maxLength,
41
98
  hint,
42
99
  error,
100
+ valid,
43
101
  onBlur,
44
102
  motion = "full",
45
103
  testHintText,
46
104
  trailing,
105
+ labels: labelsProp,
47
106
  style,
48
107
  testID
49
108
  }) {
50
- const theme = useLoamTheme();
109
+ const labels = useLabels("cardForm", DEFAULT_LABELS, labelsProp);
110
+ const theme = useLoamTheme("card-form");
51
111
  const hasError = Boolean(error);
52
112
  const { styles } = useStyles(sheet, { invalid: hasError });
53
113
  const labelId = React.useId();
@@ -61,8 +121,9 @@ function DigitsField({
61
121
  focusRef.current = () => inputRef.current?.focus();
62
122
  const register = run?.register;
63
123
  React.useEffect(() => register?.(field, () => focusRef.current()), [register, field]);
124
+ const isValid = Boolean(valid) && !hasError;
64
125
  const tone = hasError ? { border: theme.color.danger, fill: theme.color.dangerSoft } : focused ? { border: theme.focus.ringColor, fill: theme.color.surface } : { border: theme.color.borderStrong, fill: theme.color.surface2 };
65
- const animate = useResolvedMotion(motion) === "full";
126
+ const animate = useResolvedMotion(motion, "card-form") === "full";
66
127
  const easing = React.useMemo(() => Easing.bezier(...theme.easing.base), [theme.easing.base]);
67
128
  const borderColor = useColorTransition(tone.border, theme.duration.base, easing, animate);
68
129
  const backgroundColor = useColorTransition(tone.fill, theme.duration.base, easing, animate);
@@ -100,7 +161,17 @@ function DigitsField({
100
161
  }
101
162
  }
102
163
  ),
103
- hasError ? /* @__PURE__ */ jsx(View, { "aria-hidden": true, children: /* @__PURE__ */ jsx(Icon, { name: "alert-triangle", size: theme.ctl.icon.lg, color: theme.color.dangerOnSoft }) }) : trailing
164
+ hasError ? /* @__PURE__ */ jsx(View, { "aria-hidden": true, children: /* @__PURE__ */ jsx(Icon, { name: "alert-triangle", size: theme.ctl.icon.lg, color: theme.color.dangerOnSoft }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
165
+ trailing,
166
+ isValid ? /* @__PURE__ */ jsx(View, { accessibilityRole: "image", accessibilityLabel: labels.valid, children: /* @__PURE__ */ jsx(
167
+ Icon,
168
+ {
169
+ name: "check-circle",
170
+ size: theme.ctl.icon.lg,
171
+ color: theme.color.goodOnSoft
172
+ }
173
+ ) }) : null
174
+ ] })
104
175
  ] }),
105
176
  /* @__PURE__ */ jsx(ExpiryHint, { nativeID: messageId, hint, error }),
106
177
  testHintText ? /* @__PURE__ */ jsx(Text, { nativeID: testId, style: styles.testHint, children: testHintText }) : null
@@ -110,17 +181,20 @@ function CardNumberField({
110
181
  value,
111
182
  brand,
112
183
  complete,
113
- label = "Card number",
184
+ label,
114
185
  hint,
115
186
  error,
187
+ valid,
116
188
  testHint = false,
117
189
  onChange,
118
190
  onComplete,
119
191
  onBlur,
120
192
  motion,
193
+ labels: labelsProp,
121
194
  style,
122
195
  testID
123
196
  }) {
197
+ const labels = useLabels("cardForm", DEFAULT_LABELS, labelsProp);
124
198
  const result = formatCard(value);
125
199
  const resolvedBrand = brand ?? result.brand;
126
200
  const isComplete = complete ?? result.complete;
@@ -129,24 +203,26 @@ function CardNumberField({
129
203
  if (isComplete && !wasComplete.current) onComplete?.();
130
204
  wasComplete.current = isComplete;
131
205
  }, [isComplete, onComplete]);
132
- const testHintText = testHint === true ? TEST_HINT : testHint || void 0;
206
+ const testHintText = testHint === true ? labels.testHint : testHint || void 0;
133
207
  return /* @__PURE__ */ jsx(
134
208
  DigitsField,
135
209
  {
136
210
  field: "number",
137
- label,
211
+ label: label ?? labels.cardNumber,
138
212
  digits: result.digits,
139
213
  format: (d) => formatCard(d).text,
140
214
  normalize: (typed) => formatCard(onlyDigits(typed)).digits,
141
215
  onDigits: onChange,
142
216
  hint,
143
217
  error,
218
+ valid,
144
219
  onBlur,
145
220
  motion,
146
221
  autoComplete: "cc-number",
147
- placeholder: "1234 5678 9012 3456",
222
+ placeholder: labels.numberPlaceholder,
223
+ labels: labelsProp,
148
224
  testHintText: testHintText || void 0,
149
- trailing: /* @__PURE__ */ jsx(CardBrandMark, { brand: resolvedBrand.id }),
225
+ trailing: /* @__PURE__ */ jsx(BrandSwap, { brand: resolvedBrand.id }),
150
226
  style,
151
227
  testID
152
228
  }
@@ -154,17 +230,20 @@ function CardNumberField({
154
230
  }
155
231
  function ExpiryField({
156
232
  value,
157
- label = "Expiry",
158
- hint = "MM/YY",
233
+ label,
234
+ hint,
159
235
  error,
236
+ valid,
160
237
  onChange,
161
238
  onComplete,
162
239
  onBackspaceOut,
163
240
  onBlur,
164
241
  motion,
242
+ labels: labelsProp,
165
243
  style,
166
244
  testID
167
245
  }) {
246
+ const labels = useLabels("cardForm", DEFAULT_LABELS, labelsProp);
168
247
  const digits = onlyDigits(formatExpiry(value));
169
248
  const wasComplete = React.useRef(digits.length === 4);
170
249
  React.useEffect(() => {
@@ -176,18 +255,20 @@ function ExpiryField({
176
255
  DigitsField,
177
256
  {
178
257
  field: "expiry",
179
- label,
258
+ label: label ?? labels.expiry,
180
259
  digits,
181
260
  format: (d) => formatExpiry(d),
182
261
  normalize: (typed) => onlyDigits(formatExpiry(onlyDigits(typed))),
183
262
  onDigits: onChange,
184
263
  onBackspaceOut,
185
- hint,
264
+ hint: hint ?? labels.expiryHint,
186
265
  error,
266
+ valid,
187
267
  onBlur,
188
268
  motion,
189
269
  autoComplete: "cc-exp",
190
- placeholder: "MM/YY",
270
+ placeholder: labels.expiryHint,
271
+ labels: labelsProp,
191
272
  maxLength: 5,
192
273
  style,
193
274
  testID
@@ -197,17 +278,20 @@ function ExpiryField({
197
278
  function CvcField({
198
279
  value,
199
280
  digits = 3,
200
- label = "Security code",
281
+ label,
201
282
  hint,
202
283
  error,
284
+ valid,
203
285
  onChange,
204
286
  onComplete,
205
287
  onBackspaceOut,
206
288
  onBlur,
207
289
  motion,
290
+ labels: labelsProp,
208
291
  style,
209
292
  testID
210
293
  }) {
294
+ const labels = useLabels("cardForm", DEFAULT_LABELS, labelsProp);
211
295
  const clamp = React.useCallback(
212
296
  (typed) => onlyDigits(typed).slice(0, digits),
213
297
  [digits]
@@ -223,7 +307,7 @@ function CvcField({
223
307
  DigitsField,
224
308
  {
225
309
  field: "cvc",
226
- label,
310
+ label: label ?? labels.securityCode,
227
311
  digits: machine,
228
312
  format: (d) => d,
229
313
  normalize: clamp,
@@ -231,11 +315,13 @@ function CvcField({
231
315
  onBackspaceOut,
232
316
  hint,
233
317
  error,
318
+ valid,
234
319
  onBlur,
235
320
  motion,
236
321
  autoComplete: "cc-csc",
237
322
  placeholder: digits === 4 ? "1234" : "123",
238
323
  maxLength: digits,
324
+ labels: labelsProp,
239
325
  style,
240
326
  testID
241
327
  }
@@ -303,18 +389,18 @@ var sheet = createStyleSheet((theme) => ({
303
389
  color: theme.color.text3
304
390
  }
305
391
  }));
306
- function validateCard(value, brand, now = 0) {
392
+ function validateCard(value, brand, now = 0, labels) {
307
393
  const resolved = brand ?? formatCard(value.number).brand;
308
394
  const errors = {};
309
- const number = validCardNumber(value.number);
395
+ const number = validCardNumber(value.number, labels);
310
396
  if (!number.ok) errors.number = number.why;
311
397
  if (value.expiry.length === 0) {
312
- errors.expiry = CARD_COPY.expiryEmpty;
398
+ errors.expiry = resolvePayLabels(labels).cardCopy.expiryEmpty;
313
399
  } else {
314
- const expiry = validExpiry(formatExpiry(value.expiry), now);
400
+ const expiry = validExpiry(formatExpiry(value.expiry), now, labels);
315
401
  if (!expiry.ok) errors.expiry = expiry.why;
316
402
  }
317
- const cvc = validCvc(value.cvc, resolved);
403
+ const cvc = validCvc(value.cvc, resolved, labels);
318
404
  if (!cvc.ok) errors.cvc = cvc.why;
319
405
  const order = ["number", "expiry", "cvc"];
320
406
  const firstBlocking = order.find((field) => errors[field] !== void 0) ?? null;
@@ -330,19 +416,23 @@ function CardForm({
330
416
  layout = "auto",
331
417
  testHint = false,
332
418
  now = 0,
333
- saveLabel = "Save this card for next time",
419
+ saveLabel,
420
+ labels: labelsProp,
334
421
  onChange,
335
422
  onFieldBlur,
336
423
  onSaveChange,
337
424
  style,
338
425
  testID
339
426
  }) {
340
- const theme = useLoamTheme();
427
+ const labels = useLabels("cardForm", DEFAULT_LABELS, labelsProp);
428
+ const pay = usePayLabels(labelsProp);
429
+ const theme = useLoamTheme("card-form");
341
430
  const { width } = useWindowDimensions();
342
431
  const asRow = layout === "row" || layout === "auto" && width >= theme.breakpoint.tablet;
343
432
  const { styles } = useStyles(sheet2, { asRow });
344
433
  const resolvedBrand = brand ?? formatCard(value.number).brand;
345
434
  const [shown, setShown] = React.useState([]);
435
+ const [passed, setPassed] = React.useState([]);
346
436
  const isShown = (field) => shown.includes(field);
347
437
  const focusers = React.useRef(/* @__PURE__ */ new Map());
348
438
  const run = React.useMemo(
@@ -357,9 +447,14 @@ function CardForm({
357
447
  []
358
448
  );
359
449
  const focus = (field) => focusers.current.get(field)?.();
360
- const own = validateCard(value, resolvedBrand, now).errors;
450
+ const own = validateCard(value, resolvedBrand, now, pay).errors;
361
451
  const errorFor = (field) => errors?.[field] ?? (isShown(field) ? own[field] : void 0);
452
+ const validFor = (field) => passed.includes(field) && own[field] === void 0 && errors?.[field] === void 0;
362
453
  const handleBlur = (field) => () => {
454
+ const ok = own[field] === void 0;
455
+ setPassed(
456
+ (current) => ok ? current.includes(field) ? current : [...current, field] : current.filter((f) => f !== field)
457
+ );
363
458
  setShown((current) => {
364
459
  const failing = own[field] !== void 0;
365
460
  if (failing) return current.includes(field) ? current : [...current, field];
@@ -375,7 +470,9 @@ function CardForm({
375
470
  value: value.number,
376
471
  brand: resolvedBrand,
377
472
  error: errorFor("number"),
473
+ valid: validFor("number"),
378
474
  testHint,
475
+ labels: labelsProp,
379
476
  style: styles.numberField,
380
477
  onChange: (raw) => onChange({ number: raw }),
381
478
  onComplete: () => focus("expiry"),
@@ -387,6 +484,8 @@ function CardForm({
387
484
  {
388
485
  value: value.expiry,
389
486
  error: errorFor("expiry"),
487
+ valid: validFor("expiry"),
488
+ labels: labelsProp,
390
489
  onChange: (raw) => onChange({ expiry: raw }),
391
490
  onComplete: () => focus("cvc"),
392
491
  onBackspaceOut: () => focus("number"),
@@ -399,6 +498,8 @@ function CardForm({
399
498
  value: value.cvc,
400
499
  digits: resolvedBrand.cvc,
401
500
  error: errorFor("cvc"),
501
+ valid: validFor("cvc"),
502
+ labels: labelsProp,
402
503
  onChange: (raw) => onChange({ cvc: raw }),
403
504
  onBackspaceOut: () => focus("expiry"),
404
505
  onBlur: handleBlur("cvc")
@@ -408,7 +509,7 @@ function CardForm({
408
509
  showName ? /* @__PURE__ */ jsx(
409
510
  TextField,
410
511
  {
411
- label: "Name on card",
512
+ label: labels.nameOnCard,
412
513
  autoComplete: "cc-name",
413
514
  size: "lg",
414
515
  value: value.name ?? "",
@@ -417,17 +518,14 @@ function CardForm({
417
518
  onBlur: handleBlur("name")
418
519
  }
419
520
  ) : null,
420
- showSave ? /* @__PURE__ */ jsxs(View, { style: styles.saveRow, children: [
421
- /* @__PURE__ */ jsx(
422
- Checkbox,
423
- {
424
- checked: save,
425
- onCheckedChange: (next) => onSaveChange?.(next),
426
- accessibilityLabel: saveLabel
427
- }
428
- ),
429
- /* @__PURE__ */ jsx(Text, { style: styles.saveLabel, children: saveLabel })
430
- ] }) : null
521
+ showSave ? /* @__PURE__ */ jsx(View, { style: styles.saveRow, children: /* @__PURE__ */ jsx(
522
+ Checkbox,
523
+ {
524
+ checked: save,
525
+ onCheckedChange: (next) => onSaveChange?.(next),
526
+ label: saveLabel ?? labels.saveCard
527
+ }
528
+ ) }) : null
431
529
  ] }) });
432
530
  }
433
531
  var sheet2 = createStyleSheet((theme) => ({
@@ -452,12 +550,6 @@ var sheet2 = createStyleSheet((theme) => ({
452
550
  alignItems: "center",
453
551
  gap: theme.space.s3,
454
552
  minHeight: theme.tapMin
455
- },
456
- saveLabel: {
457
- flexShrink: 1,
458
- fontFamily: theme.font.sans,
459
- fontSize: theme.fontSize[14],
460
- color: theme.color.text
461
553
  }
462
554
  }));
463
555
 
@@ -1,11 +1,16 @@
1
- import { useThinkingPulse } from './chunk-XXXEFXY5.js';
1
+ import { useThinkingPulse } from './chunk-W74TXYFB.js';
2
2
  import { NODE_STATE_WORD, NODE_STATE_ICON, NODE_STATE_SHAPE } from './chunk-YLLCXTMC.js';
3
- import { Icon } from './chunk-TKVFVF5D.js';
3
+ import { useLabels } from './chunk-APCWFOZW.js';
4
+ import { Icon } from './chunk-UXGIW7OK.js';
4
5
  import * as React from 'react';
5
6
  import { View, Text, ScrollView, Animated, Easing } from 'react-native';
6
7
  import { createStyleSheet, useStyles, useLoamTheme } from '@btndprojects/loam-theme-native';
7
8
  import { jsxs, jsx } from 'react/jsx-runtime';
8
9
 
10
+ var DEFAULT_LABELS = {
11
+ stage: (label, state) => `${label}: ${state}`,
12
+ states: { ...NODE_STATE_WORD }
13
+ };
9
14
  var NODE_BOX = { sm: 28, md: 36, lg: 44 };
10
15
  var NODE_ICON = { sm: 14, md: 18, lg: 22 };
11
16
  function StageNode({
@@ -14,7 +19,7 @@ function StageNode({
14
19
  pulse
15
20
  }) {
16
21
  const { styles } = useStyles(sheet, { state });
17
- const theme = useLoamTheme();
22
+ const theme = useLoamTheme("stage-timeline");
18
23
  const box = NODE_BOX[size];
19
24
  const pulseStyle = useThinkingPulse(pulse);
20
25
  const glyphColor = state === "pending" ? theme.color.text3 : theme.status[state];
@@ -39,7 +44,7 @@ function Connector({
39
44
  motion
40
45
  }) {
41
46
  const { styles } = useStyles(sheet);
42
- const theme = useLoamTheme();
47
+ const theme = useLoamTheme("stage-timeline");
43
48
  const horizontal = orientation === "horizontal";
44
49
  const completed = from === "done";
45
50
  const animate = motion === "full" && completed && !theme.reduceMotion;
@@ -83,17 +88,19 @@ function StageTimeline({
83
88
  orientation = "horizontal",
84
89
  size = "md",
85
90
  motion = "full",
91
+ labels: labelsProp,
86
92
  style,
87
93
  testID
88
94
  }) {
95
+ const labels = useLabels("stageTimeline", DEFAULT_LABELS, labelsProp);
89
96
  const { styles } = useStyles(sheet, { size });
90
- const theme = useLoamTheme();
97
+ const theme = useLoamTheme("stage-timeline");
91
98
  const horizontal = orientation === "horizontal";
92
99
  const lastIndex = stages.length - 1;
93
100
  const pulseOn = motion === "full" && !theme.reduceMotion;
94
101
  const items = stages.map((stage, index) => {
95
102
  const isWorking = stage.state === "working";
96
- const name = `${stage.label}: ${NODE_STATE_WORD[stage.state]}`;
103
+ const name = labels.stage(stage.label, labels.states[stage.state]);
97
104
  const next = stages[index + 1];
98
105
  const showConnector = index < lastIndex && next !== void 0;
99
106
  const currentAttr = isWorking ? { "aria-current": "step" } : {};