@btndprojects/loam-ui-native 0.0.0-stage → 0.1.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 (269) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -2
  3. package/dist/accordion/index.js +3 -0
  4. package/dist/adaptive/index.js +2 -0
  5. package/dist/alert/index.js +3 -0
  6. package/dist/analyzer/index.js +6 -0
  7. package/dist/announcement/index.js +6 -0
  8. package/dist/audio-player/index.js +3 -0
  9. package/dist/avatar/index.js +3 -0
  10. package/dist/avatar-group/index.js +3 -0
  11. package/dist/badge/index.js +5 -0
  12. package/dist/banner/index.js +2 -0
  13. package/dist/board/index.js +7 -0
  14. package/dist/button/index.js +5 -0
  15. package/dist/camera-permission/index.js +13 -0
  16. package/dist/capture-result/index.js +18 -0
  17. package/dist/card/index.js +4 -0
  18. package/dist/card-form/index.js +10 -0
  19. package/dist/carousel/index.js +2 -0
  20. package/dist/chart/index.js +6 -0
  21. package/dist/charts/index.js +7 -0
  22. package/dist/checkbox/index.js +7 -0
  23. package/dist/checklist/index.js +10 -0
  24. package/dist/checkout/index.js +13 -0
  25. package/dist/chip/index.js +7 -0
  26. package/dist/chunk-223Q2T2Q.js +229 -0
  27. package/dist/chunk-2A5NIQAK.js +254 -0
  28. package/dist/chunk-2GK6PHGE.js +363 -0
  29. package/dist/chunk-2WUTXHMU.js +1 -0
  30. package/dist/chunk-2ZZ7TDJ4.js +324 -0
  31. package/dist/chunk-35OFI3JG.js +499 -0
  32. package/dist/chunk-3ARE4TES.js +195 -0
  33. package/dist/chunk-3ECPOSKO.js +1 -0
  34. package/dist/chunk-3ENTMPQY.js +229 -0
  35. package/dist/chunk-3HJH6FF4.js +98 -0
  36. package/dist/chunk-3NMD74ZU.js +4 -0
  37. package/dist/chunk-3WPW4KUN.js +182 -0
  38. package/dist/chunk-423B7SPN.js +993 -0
  39. package/dist/chunk-47FWHGUN.js +394 -0
  40. package/dist/chunk-4BXMXBJO.js +141 -0
  41. package/dist/chunk-4DS5ZWVC.js +83 -0
  42. package/dist/chunk-4GBOGOTV.js +295 -0
  43. package/dist/chunk-4SZYY6AN.js +99 -0
  44. package/dist/chunk-4YIP3CWS.js +237 -0
  45. package/dist/chunk-4YQOR7JM.js +204 -0
  46. package/dist/chunk-4ZAHCY44.js +177 -0
  47. package/dist/chunk-52X2VYTD.js +228 -0
  48. package/dist/chunk-5P26LBDL.js +1 -0
  49. package/dist/chunk-5XLRYDAX.js +1 -0
  50. package/dist/chunk-5YNTNN5A.js +177 -0
  51. package/dist/chunk-6HT2LP62.js +504 -0
  52. package/dist/chunk-6N33LFQA.js +35 -0
  53. package/dist/chunk-6X6PQ443.js +432 -0
  54. package/dist/chunk-7CFF4HXS.js +126 -0
  55. package/dist/chunk-7O2FMUPT.js +755 -0
  56. package/dist/chunk-AI4DWZCD.js +162 -0
  57. package/dist/chunk-AWJOCGFZ.js +213 -0
  58. package/dist/chunk-AZRX6SAC.js +285 -0
  59. package/dist/chunk-B54QE2FN.js +1 -0
  60. package/dist/chunk-BC475SJH.js +1 -0
  61. package/dist/chunk-BEDBFJND.js +202 -0
  62. package/dist/chunk-BTTFCMKG.js +166 -0
  63. package/dist/chunk-BV3B2HYZ.js +1635 -0
  64. package/dist/chunk-C2NTXVWM.js +98 -0
  65. package/dist/chunk-CDRZHT42.js +424 -0
  66. package/dist/chunk-CJ5EOYZE.js +62 -0
  67. package/dist/chunk-CUMUNPXY.js +128 -0
  68. package/dist/chunk-CUS3ZSCU.js +1 -0
  69. package/dist/chunk-CYRBHQQZ.js +411 -0
  70. package/dist/chunk-DHWADYZX.js +144 -0
  71. package/dist/chunk-DKCSPATL.js +1 -0
  72. package/dist/chunk-DM5QUKKO.js +326 -0
  73. package/dist/chunk-DYBH2I6W.js +1 -0
  74. package/dist/chunk-DZ255O2F.js +1 -0
  75. package/dist/chunk-E35BPSGW.js +1 -0
  76. package/dist/chunk-EJBDRVIH.js +166 -0
  77. package/dist/chunk-F43NP42L.js +1 -0
  78. package/dist/chunk-F5XNPWS7.js +1024 -0
  79. package/dist/chunk-FMYDDECK.js +1521 -0
  80. package/dist/chunk-G3HOYSF7.js +1 -0
  81. package/dist/chunk-GDKZTW34.js +395 -0
  82. package/dist/chunk-GL7B2DOW.js +134 -0
  83. package/dist/chunk-GNNJ4GCC.js +471 -0
  84. package/dist/chunk-GNZ56EUI.js +1 -0
  85. package/dist/chunk-H6NIOQHK.js +346 -0
  86. package/dist/chunk-H6PC7RDA.js +1 -0
  87. package/dist/chunk-HET4LLMX.js +129 -0
  88. package/dist/chunk-HPPW424V.js +334 -0
  89. package/dist/chunk-HQOQIBJI.js +1 -0
  90. package/dist/chunk-HU2EQNRZ.js +44 -0
  91. package/dist/chunk-HZ6CNMAF.js +870 -0
  92. package/dist/chunk-IIQTAY3J.js +715 -0
  93. package/dist/chunk-ITTYJZWX.js +271 -0
  94. package/dist/chunk-IVNRBPGC.js +1018 -0
  95. package/dist/chunk-J4KLDGI4.js +1 -0
  96. package/dist/chunk-J7Q7VCVC.js +254 -0
  97. package/dist/chunk-JDEOITQ2.js +1 -0
  98. package/dist/chunk-JNH2TYIN.js +96 -0
  99. package/dist/chunk-JNY4ZHAR.js +634 -0
  100. package/dist/chunk-JRLTGLN4.js +1 -0
  101. package/dist/chunk-JTRJJLKL.js +1 -0
  102. package/dist/chunk-JUAMLEHX.js +379 -0
  103. package/dist/chunk-JXJB2X6M.js +131 -0
  104. package/dist/chunk-KMI5ML5I.js +262 -0
  105. package/dist/chunk-KTAC4MGE.js +4 -0
  106. package/dist/chunk-LAECSR4H.js +178 -0
  107. package/dist/chunk-LK4BCSGX.js +1 -0
  108. package/dist/chunk-LOE5YNN3.js +470 -0
  109. package/dist/chunk-LRJNDEIA.js +302 -0
  110. package/dist/chunk-LSS54GLJ.js +116 -0
  111. package/dist/chunk-LZLHELAG.js +137 -0
  112. package/dist/chunk-M2LUXGKZ.js +1 -0
  113. package/dist/chunk-MOUJOP55.js +425 -0
  114. package/dist/chunk-N32RGOA5.js +159 -0
  115. package/dist/chunk-N5ZNE2YE.js +1 -0
  116. package/dist/chunk-NBNCBML6.js +1 -0
  117. package/dist/chunk-NKB7BZYK.js +167 -0
  118. package/dist/chunk-NQYBUO3K.js +1795 -0
  119. package/dist/chunk-NY2U3PBI.js +59 -0
  120. package/dist/chunk-O4AEHWII.js +464 -0
  121. package/dist/chunk-O7AE6DAF.js +146 -0
  122. package/dist/chunk-OETCUXQP.js +134 -0
  123. package/dist/chunk-OOPPQH27.js +179 -0
  124. package/dist/chunk-OPXFZ4Y5.js +204 -0
  125. package/dist/chunk-P23EQNRQ.js +338 -0
  126. package/dist/chunk-PJXUJYS6.js +248 -0
  127. package/dist/chunk-PNWUWOBF.js +1 -0
  128. package/dist/chunk-PUPM2YGF.js +376 -0
  129. package/dist/chunk-PZXZJBMP.js +620 -0
  130. package/dist/chunk-Q72LJOVE.js +169 -0
  131. package/dist/chunk-QCDXZBC5.js +247 -0
  132. package/dist/chunk-QDYDBCFP.js +197 -0
  133. package/dist/chunk-QJJ6MADV.js +274 -0
  134. package/dist/chunk-QKXCPTFS.js +349 -0
  135. package/dist/chunk-QWCMU5B2.js +860 -0
  136. package/dist/chunk-RIBDXGUG.js +108 -0
  137. package/dist/chunk-RJQOOHT2.js +214 -0
  138. package/dist/chunk-RNGLIHFA.js +191 -0
  139. package/dist/chunk-RQ3HASCC.js +6 -0
  140. package/dist/chunk-RSOJT5YW.js +124 -0
  141. package/dist/chunk-RTIKSY6A.js +1 -0
  142. package/dist/chunk-RUZHTGKB.js +237 -0
  143. package/dist/chunk-RW6ZL2FQ.js +284 -0
  144. package/dist/chunk-S7F6XLTK.js +540 -0
  145. package/dist/chunk-SBMNWWBV.js +155 -0
  146. package/dist/chunk-SDTQPRRB.js +1 -0
  147. package/dist/chunk-SYNOJOQO.js +377 -0
  148. package/dist/chunk-T753XT36.js +1 -0
  149. package/dist/chunk-TKQYWZ5V.js +196 -0
  150. package/dist/chunk-TKVFVF5D.js +95 -0
  151. package/dist/chunk-TOXAGRDQ.js +144 -0
  152. package/dist/chunk-TUTI5HOZ.js +112 -0
  153. package/dist/chunk-U7TFM2JA.js +140 -0
  154. package/dist/chunk-UC2WGUP3.js +627 -0
  155. package/dist/chunk-UWFLYMAR.js +1126 -0
  156. package/dist/chunk-UWSZB7BJ.js +1 -0
  157. package/dist/chunk-UYG5L34B.js +87 -0
  158. package/dist/chunk-VBOXAEPI.js +336 -0
  159. package/dist/chunk-VCDBXW5H.js +188 -0
  160. package/dist/chunk-VCXPHHDS.js +1 -0
  161. package/dist/chunk-VEAYTRPX.js +414 -0
  162. package/dist/chunk-VFCUIDRT.js +1 -0
  163. package/dist/chunk-VQHPQEUH.js +273 -0
  164. package/dist/chunk-VXDZFJGP.js +874 -0
  165. package/dist/chunk-WS56BL3D.js +1 -0
  166. package/dist/chunk-WSW6ZFAQ.js +98 -0
  167. package/dist/chunk-XNUVB5OL.js +375 -0
  168. package/dist/chunk-XOSCY2CW.js +242 -0
  169. package/dist/chunk-XXXEFXY5.js +99 -0
  170. package/dist/chunk-Y5CSSPV4.js +1 -0
  171. package/dist/chunk-Y6DU4J47.js +1 -0
  172. package/dist/chunk-YC6WORFL.js +535 -0
  173. package/dist/chunk-YDGVJETP.js +60 -0
  174. package/dist/chunk-YF4NSSMT.js +366 -0
  175. package/dist/chunk-YG3ZJHGU.js +223 -0
  176. package/dist/chunk-YIJ55TBC.js +1 -0
  177. package/dist/chunk-YKZ4RZZF.js +1 -0
  178. package/dist/chunk-YLLCXTMC.js +37 -0
  179. package/dist/chunk-YTA74UZR.js +1 -0
  180. package/dist/chunk-YTFKPRUK.js +845 -0
  181. package/dist/chunk-Z7H7VSFZ.js +323 -0
  182. package/dist/chunk-ZK2H4O5P.js +1 -0
  183. package/dist/chunk-ZVFE5QGU.js +524 -0
  184. package/dist/coachmark/index.js +4 -0
  185. package/dist/code-block/index.js +4 -0
  186. package/dist/color-field/index.js +7 -0
  187. package/dist/commerce/index.js +20 -0
  188. package/dist/connectivity/index.js +2 -0
  189. package/dist/context-menu/index.js +5 -0
  190. package/dist/copy-button/index.js +3 -0
  191. package/dist/data-grid/index.js +24 -0
  192. package/dist/date-range-picker/index.js +13 -0
  193. package/dist/description-list/index.js +2 -0
  194. package/dist/dialog/index.js +3 -0
  195. package/dist/empty-state/index.js +3 -0
  196. package/dist/error-summary/index.js +3 -0
  197. package/dist/fab/index.js +2 -0
  198. package/dist/file-upload/index.js +9 -0
  199. package/dist/filter-bar/index.js +8 -0
  200. package/dist/flow-run/index.js +14 -0
  201. package/dist/form/index.js +3 -0
  202. package/dist/gallery/index.js +2 -0
  203. package/dist/header/index.js +5 -0
  204. package/dist/hold-to-confirm/index.js +4 -0
  205. package/dist/index.d.ts +22883 -0
  206. package/dist/index.js +158 -0
  207. package/dist/infinite-list/index.js +2 -0
  208. package/dist/inline-edit/index.js +5 -0
  209. package/dist/input/index.js +5 -0
  210. package/dist/interactions/index.js +2 -0
  211. package/dist/invoice/index.js +10 -0
  212. package/dist/kbd/index.js +1 -0
  213. package/dist/keyboard/index.js +3 -0
  214. package/dist/list-row/index.js +7 -0
  215. package/dist/log-viewer/index.js +2 -0
  216. package/dist/map-view/index.js +3 -0
  217. package/dist/markdown/index.js +6 -0
  218. package/dist/metric/index.js +4 -0
  219. package/dist/money/index.js +3 -0
  220. package/dist/nav-drawer/index.js +2 -0
  221. package/dist/navigation/index.js +2 -0
  222. package/dist/notification-center/index.js +16 -0
  223. package/dist/number-roll/index.js +3 -0
  224. package/dist/one-handed/index.js +5 -0
  225. package/dist/os-surfaces/index.js +3 -0
  226. package/dist/otp/index.js +7 -0
  227. package/dist/page-header/index.js +1 -0
  228. package/dist/payment-method/index.js +12 -0
  229. package/dist/payment-status/index.js +16 -0
  230. package/dist/permission/index.js +2 -0
  231. package/dist/picker/index.js +7 -0
  232. package/dist/progress/index.js +5 -0
  233. package/dist/pull-to-refresh/index.js +4 -0
  234. package/dist/radio-group/index.js +6 -0
  235. package/dist/rating/index.js +2 -0
  236. package/dist/receivables/index.js +20 -0
  237. package/dist/refund/index.js +16 -0
  238. package/dist/save-status/index.js +3 -0
  239. package/dist/scroll-area/index.js +1 -0
  240. package/dist/search-bar/index.js +5 -0
  241. package/dist/segmented-control/index.js +5 -0
  242. package/dist/sheet/index.js +4 -0
  243. package/dist/skeleton/index.js +2 -0
  244. package/dist/slider/index.js +5 -0
  245. package/dist/spinner/index.js +2 -0
  246. package/dist/split-button/index.js +7 -0
  247. package/dist/spotlight/index.js +2 -0
  248. package/dist/stage-timeline/index.js +4 -0
  249. package/dist/status-dot/index.js +2 -0
  250. package/dist/stepper/index.js +6 -0
  251. package/dist/streaming-text/index.js +3 -0
  252. package/dist/survey/index.js +19 -0
  253. package/dist/switch/index.js +5 -0
  254. package/dist/system-state/index.js +4 -0
  255. package/dist/tab-bar/index.js +2 -0
  256. package/dist/tabs/index.js +2 -0
  257. package/dist/textarea/index.js +6 -0
  258. package/dist/thinking/index.js +2 -0
  259. package/dist/timeline/index.js +4 -0
  260. package/dist/toast/index.js +2 -0
  261. package/dist/toolbar/index.js +2 -0
  262. package/dist/tour/index.js +11 -0
  263. package/dist/truncation-notice/index.js +2 -0
  264. package/dist/update-notice/index.js +11 -0
  265. package/dist/video-player/index.js +2 -0
  266. package/dist/viewfinder/index.js +5 -0
  267. package/dist/widget/index.js +4 -0
  268. package/dist/wizard/index.js +6 -0
  269. package/package.json +76 -3
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,87 @@
1
+ import { useThinkingPulse } from './chunk-XXXEFXY5.js';
2
+ import 'react';
3
+ import { View, Animated, Text } from 'react-native';
4
+ import { createStyleSheet, useStyles, useLoamTheme } from '@btndprojects/loam-theme-native';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function StatusDot({
8
+ state,
9
+ size = "md",
10
+ label,
11
+ pulse,
12
+ motion = "full",
13
+ accessibilityLabel,
14
+ style,
15
+ testID
16
+ }) {
17
+ const { styles } = useStyles(sheet, { state, size });
18
+ const theme = useLoamTheme();
19
+ const shouldPulse = state === "working" && (pulse ?? true) && motion === "full" && !theme.reduceMotion;
20
+ const pulseStyle = useThinkingPulse(shouldPulse);
21
+ const name = accessibilityLabel || label || `Status: ${state}`;
22
+ return /* @__PURE__ */ jsxs(
23
+ View,
24
+ {
25
+ accessibilityRole: "image",
26
+ accessibilityLabel: name,
27
+ testID,
28
+ style: [styles.container, style],
29
+ children: [
30
+ /* @__PURE__ */ jsx(Animated.View, { style: [styles.dot, pulseStyle] }),
31
+ label ? /* @__PURE__ */ jsx(Text, { style: styles.label, children: label }) : null
32
+ ]
33
+ }
34
+ );
35
+ }
36
+ var sheet = createStyleSheet((theme) => ({
37
+ container: {
38
+ flexDirection: "row",
39
+ alignItems: "center",
40
+ alignSelf: "flex-start",
41
+ gap: theme.space.s2
42
+ },
43
+ // Shape encodes the state; colour only reinforces it. `borderRadius: 2` is a
44
+ // graphical-glyph radius (like the charts legend chip's raw px) — a real token
45
+ // (`radius.xs` = 4) would round an 8px square into a circle and erase the
46
+ // shape distinction. `radius.full` clamps the round states to a true circle.
47
+ dot: {
48
+ variants: {
49
+ state: {
50
+ working: { backgroundColor: theme.status.working, borderRadius: theme.radius.full },
51
+ waiting: { backgroundColor: theme.status.waiting, borderRadius: theme.radius[2] },
52
+ done: { backgroundColor: theme.status.done, borderRadius: theme.radius.full },
53
+ crashed: {
54
+ backgroundColor: theme.status.crashed,
55
+ borderRadius: theme.radius[2],
56
+ transform: [{ rotate: "45deg" }]
57
+ },
58
+ conflict: {
59
+ backgroundColor: theme.status.conflictSoft,
60
+ borderRadius: theme.radius[2],
61
+ borderWidth: theme.borderWidth.thick,
62
+ borderColor: theme.status.conflict,
63
+ transform: [{ rotate: "45deg" }]
64
+ },
65
+ pending: {
66
+ backgroundColor: "transparent",
67
+ borderRadius: theme.radius.full,
68
+ borderWidth: theme.borderWidth.thick,
69
+ borderColor: theme.status.pending
70
+ }
71
+ },
72
+ size: {
73
+ sm: { width: theme.space[8], height: theme.space[8] },
74
+ md: { width: theme.space[10], height: theme.space[10] }
75
+ }
76
+ }
77
+ },
78
+ label: {
79
+ fontFamily: theme.font.sans,
80
+ color: theme.color.text,
81
+ fontSize: theme.type.footnote.fontSize,
82
+ lineHeight: theme.type.footnote.lineHeight,
83
+ letterSpacing: theme.type.footnote.letterSpacing
84
+ }
85
+ }));
86
+
87
+ export { StatusDot };
@@ -0,0 +1,336 @@
1
+ import { Icon } from './chunk-TKVFVF5D.js';
2
+ import 'react';
3
+ import { Text, View } from 'react-native';
4
+ import { createStyleSheet, useStyles, useLoamTheme } from '@btndprojects/loam-theme-native';
5
+ import { moneyParts } from '@btndprojects/loam-pay';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
+
8
+ function Amount({
9
+ minor,
10
+ currency,
11
+ size = "md",
12
+ weight,
13
+ tone = "default",
14
+ strike = false,
15
+ signed = false,
16
+ compact = false,
17
+ noSymbol = false,
18
+ align,
19
+ locale,
20
+ style,
21
+ testID
22
+ }) {
23
+ const hero = size === "hero";
24
+ const resolvedWeight = weight ?? (hero ? "bold" : "medium");
25
+ const { styles } = useStyles(sheet, {
26
+ size,
27
+ weight: resolvedWeight,
28
+ // `default` is a reserved key in a Unistyles variant group (it names the
29
+ // group's fallback), so the surface's own ink is spelled `ink` in the sheet.
30
+ // The prop keeps the shared vocabulary the web half uses.
31
+ tone: tone === "default" ? "ink" : tone,
32
+ align: align ?? "none",
33
+ strike
34
+ });
35
+ const parts = moneyParts(minor, currency, { locale, noSymbol, compact, signed });
36
+ return /* @__PURE__ */ jsx(Text, { testID, numberOfLines: 1, style: [styles.amount, style], children: hero && parts.frac ? /* @__PURE__ */ jsxs(Fragment, { children: [
37
+ /* @__PURE__ */ jsx(Text, { style: styles.amount, children: parts.main }),
38
+ /* @__PURE__ */ jsx(Text, { style: styles.frac, children: parts.frac }),
39
+ parts.tail ? /* @__PURE__ */ jsx(Text, { style: styles.amount, children: parts.tail }) : null
40
+ ] }) : `${parts.main}${parts.frac}${parts.tail ?? ""}` });
41
+ }
42
+ function AmountRange({
43
+ perInstalment,
44
+ count,
45
+ total,
46
+ currency,
47
+ size = "md",
48
+ totalLabel = "total",
49
+ locale,
50
+ style,
51
+ testID
52
+ }) {
53
+ const { styles } = useStyles(sheet, { joinSize: size });
54
+ return /* @__PURE__ */ jsxs(View, { testID, style: [styles.rangeRow, style], children: [
55
+ /* @__PURE__ */ jsx(
56
+ Amount,
57
+ {
58
+ testID: "amount-range-instalment",
59
+ minor: perInstalment,
60
+ currency,
61
+ size,
62
+ locale
63
+ }
64
+ ),
65
+ /* @__PURE__ */ jsx(Text, { style: styles.join, children: `\xD7 ${count}` }),
66
+ /* @__PURE__ */ jsx(Text, { "aria-hidden": true, style: styles.joinDot, children: "\xB7" }),
67
+ /* @__PURE__ */ jsx(Text, { style: styles.join, children: totalLabel }),
68
+ /* @__PURE__ */ jsx(
69
+ Amount,
70
+ {
71
+ testID: "amount-range-total",
72
+ minor: total,
73
+ currency,
74
+ size,
75
+ locale
76
+ }
77
+ )
78
+ ] });
79
+ }
80
+ function PriceRow({
81
+ label,
82
+ minor,
83
+ currency,
84
+ strong = false,
85
+ tone,
86
+ rule = false,
87
+ noSymbol = false,
88
+ signed = false,
89
+ locale,
90
+ style,
91
+ testID
92
+ }) {
93
+ const { styles } = useStyles(sheet, { rule, strong });
94
+ return /* @__PURE__ */ jsxs(View, { testID, style: [styles.priceRow, style], children: [
95
+ typeof label === "string" ? /* @__PURE__ */ jsx(Text, { numberOfLines: 2, style: styles.priceLabel, children: label }) : label,
96
+ /* @__PURE__ */ jsx(
97
+ Amount,
98
+ {
99
+ minor,
100
+ currency,
101
+ size: strong ? "lg" : "sm",
102
+ weight: strong ? "bold" : "medium",
103
+ tone,
104
+ noSymbol,
105
+ signed,
106
+ locale
107
+ }
108
+ )
109
+ ] });
110
+ }
111
+ function FxNote({
112
+ currency,
113
+ rateLine,
114
+ note = "Your bank may convert at its own rate \u2014 we show the rate we used:",
115
+ style,
116
+ testID
117
+ }) {
118
+ const theme = useLoamTheme();
119
+ const { styles } = useStyles(sheet);
120
+ return /* @__PURE__ */ jsxs(View, { testID, style: [styles.fxNote, style], children: [
121
+ /* @__PURE__ */ jsx(Icon, { name: "info", size: theme.icon.sm, color: theme.color.infoOnSoft }),
122
+ /* @__PURE__ */ jsxs(Text, { style: styles.fxText, children: [
123
+ `Charged in ${currency}. ${note} `,
124
+ /* @__PURE__ */ jsx(Text, { style: styles.fxRate, children: rateLine })
125
+ ] })
126
+ ] });
127
+ }
128
+ function SummaryItemRow({
129
+ name,
130
+ detail,
131
+ qty,
132
+ minor,
133
+ currency,
134
+ icon,
135
+ noSymbol = false,
136
+ locale,
137
+ style,
138
+ testID
139
+ }) {
140
+ const theme = useLoamTheme();
141
+ const { styles } = useStyles(sheet);
142
+ return /* @__PURE__ */ jsxs(View, { testID, style: [styles.itemRow, style], children: [
143
+ icon ? /* @__PURE__ */ jsx(View, { "aria-hidden": true, style: styles.itemTile, children: /* @__PURE__ */ jsx(Icon, { name: icon, size: theme.icon.sm, color: theme.color.text2 }) }) : null,
144
+ /* @__PURE__ */ jsxs(View, { style: styles.itemText, children: [
145
+ /* @__PURE__ */ jsxs(Text, { numberOfLines: 1, style: styles.itemName, children: [
146
+ name,
147
+ qty > 1 ? /* @__PURE__ */ jsx(Text, { style: styles.itemQty, children: ` \xD7 ${qty}` }) : null
148
+ ] }),
149
+ detail ? /* @__PURE__ */ jsx(Text, { numberOfLines: 1, style: styles.itemDetail, children: detail }) : null
150
+ ] }),
151
+ /* @__PURE__ */ jsx(Amount, { minor, currency, size: "sm", noSymbol, locale })
152
+ ] });
153
+ }
154
+ var sheet = createStyleSheet((theme) => ({
155
+ /**
156
+ * The amount itself.
157
+ *
158
+ * Sizes come from the numeric type ramp rather than a `type.*` role because
159
+ * here the size genuinely *is* the decision — a figure in a table cell, a
160
+ * figure on a button, a figure that is the whole screen. `hero` is 40px with
161
+ * tight tracking (the spec asks for it above 30px), and its fraction is 22px:
162
+ * 56% of 40 is 22.4, so the ramp already holds the value.
163
+ */
164
+ amount: {
165
+ fontFamily: theme.font.sans,
166
+ // P11: tabular figures everywhere, so a column lines up on the separator.
167
+ fontVariant: ["tabular-nums"],
168
+ variants: {
169
+ size: {
170
+ sm: {
171
+ fontSize: theme.fontSize[13],
172
+ lineHeight: theme.fontSize[13] * theme.lineHeight.snug
173
+ },
174
+ md: {
175
+ fontSize: theme.fontSize[15],
176
+ lineHeight: theme.fontSize[15] * theme.lineHeight.snug
177
+ },
178
+ lg: {
179
+ fontSize: theme.fontSize[22],
180
+ lineHeight: theme.fontSize[22] * theme.lineHeight.tight
181
+ },
182
+ hero: {
183
+ fontSize: theme.fontSize[40],
184
+ lineHeight: theme.fontSize[40] * theme.lineHeight.tight,
185
+ letterSpacing: theme.fontSize[40] * theme.tracking.tight
186
+ }
187
+ },
188
+ weight: {
189
+ regular: { fontWeight: theme.fontWeight.regular },
190
+ medium: { fontWeight: theme.fontWeight.medium },
191
+ bold: { fontWeight: theme.fontWeight.bold }
192
+ },
193
+ tone: {
194
+ ink: { color: theme.color.text },
195
+ muted: { color: theme.color.text2 },
196
+ subtle: { color: theme.color.text3 },
197
+ accent: { color: theme.color.accentStrong },
198
+ good: { color: theme.color.good },
199
+ warn: { color: theme.color.warn },
200
+ danger: { color: theme.color.danger }
201
+ },
202
+ // Logical alignment: `end` is the reading end, so it flips under RTL.
203
+ // `none` is the inline case — an amount inside a sentence.
204
+ align: {
205
+ none: {},
206
+ start: { alignSelf: "stretch", textAlign: theme.rtl ? "right" : "left" },
207
+ end: { alignSelf: "stretch", textAlign: theme.rtl ? "left" : "right" }
208
+ },
209
+ // A struck figure also drops to the muted ink, so the strike is never the
210
+ // only signal that the number no longer applies.
211
+ strike: {
212
+ true: { textDecorationLine: "line-through", color: theme.color.text3 },
213
+ false: {}
214
+ }
215
+ }
216
+ },
217
+ frac: {
218
+ fontFamily: theme.font.sans,
219
+ fontVariant: ["tabular-nums"],
220
+ fontSize: theme.fontSize[22],
221
+ // The ink ramp, not an opacity: a dimmed fraction cannot be measured
222
+ // against a ground the component does not know.
223
+ color: theme.color.text2
224
+ },
225
+ rangeRow: {
226
+ flexDirection: "row",
227
+ flexWrap: "wrap",
228
+ alignItems: "baseline",
229
+ gap: theme.space[6]
230
+ },
231
+ join: {
232
+ fontFamily: theme.font.sans,
233
+ color: theme.color.text2,
234
+ variants: {
235
+ joinSize: {
236
+ sm: { fontSize: theme.fontSize[13] },
237
+ md: { fontSize: theme.fontSize[15] },
238
+ lg: { fontSize: theme.fontSize[15] }
239
+ }
240
+ }
241
+ },
242
+ joinDot: {
243
+ fontFamily: theme.font.sans,
244
+ fontSize: theme.fontSize[15],
245
+ color: theme.color.text3
246
+ },
247
+ priceRow: {
248
+ flexDirection: "row",
249
+ alignItems: "baseline",
250
+ justifyContent: "space-between",
251
+ gap: theme.space.s4,
252
+ variants: {
253
+ rule: {
254
+ true: {
255
+ borderTopWidth: theme.borderWidth.base,
256
+ borderTopColor: theme.color.border,
257
+ paddingTop: theme.space[10]
258
+ },
259
+ false: {}
260
+ },
261
+ strong: { true: {}, false: {} }
262
+ }
263
+ },
264
+ priceLabel: {
265
+ flexShrink: 1,
266
+ fontFamily: theme.font.sans,
267
+ fontSize: theme.fontSize[13],
268
+ variants: {
269
+ rule: { true: {}, false: {} },
270
+ strong: {
271
+ true: { fontWeight: theme.fontWeight.bold, color: theme.color.text },
272
+ false: { color: theme.color.text2 }
273
+ }
274
+ }
275
+ },
276
+ fxNote: {
277
+ flexDirection: "row",
278
+ alignItems: "flex-start",
279
+ gap: theme.space.s2,
280
+ padding: theme.space.s3,
281
+ borderRadius: theme.radius.md,
282
+ // A soft tint needs a tone edge: `infoSoft` collapses to the plain surface
283
+ // under high contrast, and the edge is then the only thing drawing the block.
284
+ backgroundColor: theme.color.infoSoft,
285
+ borderWidth: theme.borderWidth.base,
286
+ borderColor: theme.edge.info
287
+ },
288
+ fxText: {
289
+ flexShrink: 1,
290
+ fontFamily: theme.font.sans,
291
+ fontSize: theme.fontSize[13],
292
+ lineHeight: theme.fontSize[13] * theme.lineHeight.normal,
293
+ color: theme.color.infoOnSoft
294
+ },
295
+ fxRate: {
296
+ fontFamily: theme.font.sans,
297
+ fontWeight: theme.fontWeight.semibold,
298
+ fontVariant: ["tabular-nums"],
299
+ color: theme.color.infoOnSoft
300
+ },
301
+ itemRow: {
302
+ flexDirection: "row",
303
+ alignItems: "center",
304
+ gap: theme.space.s3
305
+ },
306
+ itemTile: {
307
+ alignItems: "center",
308
+ justifyContent: "center",
309
+ width: theme.ctl.iconBtnSm,
310
+ height: theme.ctl.iconBtnSm,
311
+ borderRadius: theme.radius.md,
312
+ backgroundColor: theme.color.surface2,
313
+ borderWidth: theme.borderWidth.base,
314
+ borderColor: theme.color.border
315
+ },
316
+ itemText: { flexShrink: 1, flexGrow: 1 },
317
+ itemName: {
318
+ fontFamily: theme.font.sans,
319
+ fontWeight: theme.fontWeight.semibold,
320
+ fontSize: theme.fontSize[13],
321
+ color: theme.color.text
322
+ },
323
+ itemQty: {
324
+ fontFamily: theme.font.sans,
325
+ fontVariant: ["tabular-nums"],
326
+ fontWeight: theme.fontWeight.regular,
327
+ color: theme.color.text2
328
+ },
329
+ itemDetail: {
330
+ fontFamily: theme.font.sans,
331
+ fontSize: theme.fontSize[12],
332
+ color: theme.color.text3
333
+ }
334
+ }));
335
+
336
+ export { Amount, AmountRange, FxNote, PriceRow, SummaryItemRow };
@@ -0,0 +1,188 @@
1
+ import { useResolvedMotion } from './chunk-6N33LFQA.js';
2
+ import * as React from 'react';
3
+ import { View, ScrollView, Animated, Easing } from 'react-native';
4
+ import { createStyleSheet, useStyles, useLoamTheme } from '@btndprojects/loam-theme-native';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ var DOT_SIZE = 7;
8
+ var DOT_ACTIVE_WIDTH = 22;
9
+ function Dot({ active, motion }) {
10
+ const theme = useLoamTheme();
11
+ const { styles } = useStyles(sheet);
12
+ const width = React.useRef(
13
+ new Animated.Value(theme.space[active ? DOT_ACTIVE_WIDTH : DOT_SIZE])
14
+ ).current;
15
+ const opacity = React.useRef(new Animated.Value(active ? 1 : 0.4)).current;
16
+ React.useEffect(() => {
17
+ const targetWidth = theme.space[active ? DOT_ACTIVE_WIDTH : DOT_SIZE];
18
+ const targetOpacity = active ? 1 : 0.4;
19
+ if (motion === "none") {
20
+ width.setValue(targetWidth);
21
+ opacity.setValue(targetOpacity);
22
+ return;
23
+ }
24
+ const animations = [
25
+ Animated.timing(opacity, {
26
+ toValue: targetOpacity,
27
+ duration: theme.duration.base,
28
+ easing: Easing.bezier(...theme.easing.spring),
29
+ useNativeDriver: false
30
+ })
31
+ ];
32
+ if (motion === "full") {
33
+ animations.push(
34
+ Animated.timing(width, {
35
+ toValue: targetWidth,
36
+ duration: theme.duration.base,
37
+ easing: Easing.bezier(...theme.easing.spring),
38
+ useNativeDriver: false
39
+ })
40
+ );
41
+ } else {
42
+ width.setValue(targetWidth);
43
+ }
44
+ Animated.parallel(animations).start();
45
+ }, [active, motion, width, opacity, theme.duration.base, theme.easing.spring]);
46
+ return /* @__PURE__ */ jsx(
47
+ Animated.View,
48
+ {
49
+ testID: "carousel-dot",
50
+ style: [
51
+ styles.dot,
52
+ {
53
+ width,
54
+ opacity,
55
+ // Reference: inactive → text3, active → accent.
56
+ backgroundColor: active ? theme.color.accent : theme.color.text3
57
+ }
58
+ ]
59
+ }
60
+ );
61
+ }
62
+ function Carousel({
63
+ items,
64
+ renderItem,
65
+ children,
66
+ activeIndex,
67
+ onIndexChange,
68
+ showDots = true,
69
+ autoPlay = false,
70
+ interval = 4e3,
71
+ loop = false,
72
+ accessibilityLabel = "Carousel",
73
+ motion = "full"
74
+ }) {
75
+ const { styles } = useStyles(sheet);
76
+ const resolvedMotion = useResolvedMotion(motion);
77
+ const slides = items && renderItem ? items.map((item, index) => renderItem(item, index)) : React.Children.toArray(children);
78
+ const count = slides.length;
79
+ const isControlled = activeIndex !== void 0;
80
+ const [internal, setInternal] = React.useState(0);
81
+ const active = Math.min(
82
+ count - 1,
83
+ Math.max(0, isControlled ? activeIndex : internal)
84
+ );
85
+ const [width, setWidth] = React.useState(0);
86
+ const scrollRef = React.useRef(null);
87
+ const onLayout = (e) => {
88
+ const next = e.nativeEvent.layout.width;
89
+ setWidth((prev) => prev === next ? prev : next);
90
+ };
91
+ const goTo = React.useCallback(
92
+ (index) => {
93
+ const clamped = Math.min(count - 1, Math.max(0, index));
94
+ if (clamped === active) return;
95
+ if (!isControlled) setInternal(clamped);
96
+ onIndexChange?.(clamped);
97
+ },
98
+ [active, count, isControlled, onIndexChange]
99
+ );
100
+ const onMomentumScrollEnd = (e) => {
101
+ if (width <= 0) return;
102
+ goTo(Math.round(e.nativeEvent.contentOffset.x / width));
103
+ };
104
+ React.useEffect(() => {
105
+ if (width <= 0) return;
106
+ scrollRef.current?.scrollTo({ x: active * width, animated: resolvedMotion === "full" });
107
+ }, [active, width, resolvedMotion]);
108
+ React.useEffect(() => {
109
+ if (!autoPlay || count <= 1) return;
110
+ const id = setInterval(() => {
111
+ const next = active + 1;
112
+ if (next >= count) {
113
+ if (loop) goTo(0);
114
+ } else {
115
+ goTo(next);
116
+ }
117
+ }, interval);
118
+ return () => clearInterval(id);
119
+ }, [autoPlay, interval, loop, active, count, goTo]);
120
+ return /* @__PURE__ */ jsxs(View, { style: styles.container, role: "group", accessibilityLabel, children: [
121
+ /* @__PURE__ */ jsx(
122
+ ScrollView,
123
+ {
124
+ ref: scrollRef,
125
+ horizontal: true,
126
+ pagingEnabled: true,
127
+ focusable: true,
128
+ showsHorizontalScrollIndicator: false,
129
+ onLayout,
130
+ onMomentumScrollEnd,
131
+ scrollEventThrottle: 16,
132
+ style: styles.scroll,
133
+ children: slides.map((slide, index) => /* @__PURE__ */ jsx(
134
+ View,
135
+ {
136
+ style: [styles.page, width > 0 ? { width } : styles.pageFallback],
137
+ accessible: true,
138
+ role: "group",
139
+ accessibilityLabel: `Slide ${index + 1} of ${count}`,
140
+ children: slide
141
+ },
142
+ index
143
+ ))
144
+ }
145
+ ),
146
+ showDots && count > 1 ? /* @__PURE__ */ jsx(
147
+ View,
148
+ {
149
+ style: styles.dots,
150
+ accessible: false,
151
+ importantForAccessibility: "no-hide-descendants",
152
+ children: slides.map((_, index) => /* @__PURE__ */ jsx(Dot, { active: index === active, motion: resolvedMotion }, index))
153
+ }
154
+ ) : null
155
+ ] });
156
+ }
157
+ var sheet = createStyleSheet((theme) => ({
158
+ container: {
159
+ position: "relative",
160
+ alignSelf: "stretch",
161
+ width: "100%"
162
+ },
163
+ scroll: {
164
+ alignSelf: "stretch"
165
+ },
166
+ page: {
167
+ alignSelf: "stretch"
168
+ },
169
+ // Before the container has measured itself (e.g. first render / jsdom), fall
170
+ // back to a full-width page so content still lays out.
171
+ pageFallback: {
172
+ width: "100%"
173
+ },
174
+ dots: {
175
+ flexDirection: "row",
176
+ justifyContent: "center",
177
+ alignItems: "center",
178
+ gap: theme.space.s2,
179
+ paddingTop: theme.space.s3,
180
+ pointerEvents: "none"
181
+ },
182
+ dot: {
183
+ height: theme.space[DOT_SIZE],
184
+ borderRadius: theme.radius.full
185
+ }
186
+ }));
187
+
188
+ export { Carousel };
@@ -0,0 +1 @@
1
+