@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,11 +1,11 @@
1
- import { useColorTransition } from './chunk-ITTYJZWX.js';
1
+ import { useColorTransition } from './chunk-7BUIKDD6.js';
2
2
  import { haptics } from './chunk-NY2U3PBI.js';
3
- import { useResolvedMotion } from './chunk-6N33LFQA.js';
4
- import { Icon } from './chunk-TKVFVF5D.js';
3
+ import { Icon } from './chunk-UXGIW7OK.js';
4
+ import { useResolvedMotion, springConfig } from './chunk-J64KGCGX.js';
5
5
  import * as React from 'react';
6
- import { Easing, Animated, Pressable, Platform } from 'react-native';
6
+ import { Easing, Animated, Pressable, View, Text, Platform } from 'react-native';
7
7
  import { createStyleSheet, useLoamTheme, useStyles } from '@btndprojects/loam-theme-native';
8
- import { jsx } from 'react/jsx-runtime';
8
+ import { jsxs, jsx } from 'react/jsx-runtime';
9
9
 
10
10
  var BOX = { sm: 16, md: 24 };
11
11
  var GLYPH = { sm: 12, md: 14 };
@@ -14,7 +14,7 @@ function nextChecked(current) {
14
14
  return current === true ? false : true;
15
15
  }
16
16
  function useResolvedPlatform(explicit) {
17
- const theme = useLoamTheme();
17
+ const theme = useLoamTheme("checkbox");
18
18
  if (explicit) return explicit;
19
19
  if (Platform.OS === "ios") return "ios";
20
20
  if (Platform.OS === "android") return "android";
@@ -28,7 +28,8 @@ function Checkbox({
28
28
  platform,
29
29
  disabled = false,
30
30
  motion = "full",
31
- accessibilityLabel
31
+ accessibilityLabel,
32
+ label
32
33
  }) {
33
34
  const isControlled = checked !== void 0;
34
35
  const [internal, setInternal] = React.useState(defaultChecked);
@@ -36,30 +37,32 @@ function Checkbox({
36
37
  const isChecked = value === true;
37
38
  const isIndeterminate = value === "indeterminate";
38
39
  const isOn = isChecked || isIndeterminate;
39
- const theme = useLoamTheme();
40
+ const theme = useLoamTheme("checkbox");
40
41
  const os = useResolvedPlatform(platform);
41
42
  const { styles } = useStyles(sheet, { shape: `${os}-${size}`, disabled });
42
- const resolvedMotion = useResolvedMotion(motion);
43
+ const hasLabel = label != null && label !== "";
44
+ const resolvedMotion = useResolvedMotion(motion, "checkbox");
43
45
  const animateColour = resolvedMotion !== "none";
44
46
  const animatePress = resolvedMotion === "full";
45
47
  const easing = React.useMemo(() => Easing.bezier(...theme.easing.base), [theme.easing.base]);
48
+ const fillMs = isOn ? theme.spring.de.duration : theme.spring.fe.duration;
46
49
  const backgroundColor = useColorTransition(
47
50
  isOn ? theme.color.accent : "transparent",
48
- theme.duration.base,
51
+ fillMs,
49
52
  easing,
50
53
  animateColour
51
54
  );
52
55
  const borderColor = useColorTransition(
53
56
  isOn ? theme.color.accent : theme.color.borderStrong,
54
- theme.duration.base,
57
+ fillMs,
55
58
  easing,
56
59
  animateColour
57
60
  );
58
61
  const scale = React.useRef(new Animated.Value(1)).current;
59
62
  const spring = (to) => Animated.spring(scale, {
63
+ ...springConfig(theme, "fs"),
60
64
  toValue: to,
61
- useNativeDriver: true,
62
- ...theme.spring.press
65
+ useNativeDriver: true
63
66
  }).start();
64
67
  const handlePress = () => {
65
68
  const next = nextChecked(value);
@@ -67,33 +70,65 @@ function Checkbox({
67
70
  haptics.impact("light");
68
71
  onCheckedChange?.(next);
69
72
  };
70
- return /* @__PURE__ */ jsx(
73
+ return /* @__PURE__ */ jsxs(
71
74
  Pressable,
72
75
  {
73
76
  accessibilityRole: "checkbox",
74
- accessibilityLabel,
77
+ accessibilityLabel: accessibilityLabel ?? label,
75
78
  accessibilityState: { checked: isIndeterminate ? "mixed" : isChecked, disabled },
76
79
  "aria-checked": isIndeterminate ? "mixed" : isChecked,
77
80
  disabled,
81
+ hitSlop: hasLabel ? void 0 : Math.max(0, (theme.tapMin - BOX[size]) / 2),
82
+ style: hasLabel ? [styles.row, { minHeight: theme.tapMin }] : void 0,
78
83
  onPress: disabled ? void 0 : handlePress,
79
- onPressIn: disabled || !animatePress ? void 0 : () => spring(0.9),
84
+ onPressIn: disabled || !animatePress ? void 0 : () => spring(0.96),
80
85
  onPressOut: disabled || !animatePress ? void 0 : () => spring(1),
81
- children: /* @__PURE__ */ jsx(
82
- Animated.View,
83
- {
84
- testID: "checkbox-box",
85
- style: [styles.box, { backgroundColor, borderColor, transform: [{ scale }] }],
86
- children: isOn ? /* @__PURE__ */ jsx(
87
- Icon,
88
- {
89
- name: isIndeterminate ? "minus" : "check",
90
- size: GLYPH[size],
91
- color: theme.color.accentInk,
92
- strokeWidth: CHECK_STROKE
93
- }
94
- ) : null
95
- }
96
- )
86
+ children: [
87
+ /* @__PURE__ */ jsx(
88
+ Animated.View,
89
+ {
90
+ testID: "checkbox-box",
91
+ style: [styles.box, { backgroundColor, borderColor, transform: [{ scale }] }],
92
+ children: isOn ? /* @__PURE__ */ jsx(
93
+ Glyph,
94
+ {
95
+ name: isIndeterminate ? "minus" : "check",
96
+ size: GLYPH[size],
97
+ color: theme.color.accentInk,
98
+ animate: animatePress
99
+ },
100
+ isIndeterminate ? "minus" : "check"
101
+ ) : null
102
+ }
103
+ ),
104
+ hasLabel ? (
105
+ // Part of the control's name already — not a second element to reach.
106
+ /* @__PURE__ */ jsx(View, { accessible: false, importantForAccessibility: "no", style: styles.labelWrap, children: /* @__PURE__ */ jsx(Text, { style: styles.label, children: label }) })
107
+ ) : null
108
+ ]
109
+ }
110
+ );
111
+ }
112
+ function Glyph({
113
+ name,
114
+ size,
115
+ color,
116
+ animate
117
+ }) {
118
+ const theme = useLoamTheme("checkbox");
119
+ const p = React.useRef(new Animated.Value(animate ? 0 : 1)).current;
120
+ React.useEffect(() => {
121
+ if (!animate) return;
122
+ Animated.spring(p, { ...springConfig(theme, "ds"), toValue: 1, useNativeDriver: true }).start();
123
+ }, [animate, p, theme]);
124
+ return /* @__PURE__ */ jsx(
125
+ Animated.View,
126
+ {
127
+ style: {
128
+ opacity: p.interpolate({ inputRange: [0, 1], outputRange: [0, 1], extrapolate: "clamp" }),
129
+ transform: [{ scale: p.interpolate({ inputRange: [0, 1], outputRange: [0.5, 1] }) }]
130
+ },
131
+ children: /* @__PURE__ */ jsx(Icon, { name, size, color, strokeWidth: CHECK_STROKE })
97
132
  }
98
133
  );
99
134
  }
@@ -105,6 +140,20 @@ function boxStyle(os, size, radius) {
105
140
  };
106
141
  }
107
142
  var sheet = createStyleSheet((theme) => ({
143
+ row: { flexDirection: "row", alignItems: "center", gap: theme.space.s2 },
144
+ labelWrap: { flexShrink: 1 },
145
+ label: {
146
+ fontFamily: theme.font.sans,
147
+ fontSize: theme.type.footnote.fontSize,
148
+ lineHeight: theme.type.footnote.lineHeight,
149
+ color: theme.color.text,
150
+ variants: {
151
+ disabled: {
152
+ true: { opacity: theme.state.disabledOpacity },
153
+ false: {}
154
+ }
155
+ }
156
+ },
108
157
  // `backgroundColor` / `borderColor` are supplied at the use site as animated
109
158
  // values so the box can travel between states over `duration.base`.
110
159
  box: {
@@ -0,0 +1,176 @@
1
+ import { useLabels } from './chunk-APCWFOZW.js';
2
+ import { Icon } from './chunk-UXGIW7OK.js';
3
+ import { useResolvedMotion, motionTiming, springConfig } from './chunk-J64KGCGX.js';
4
+ import * as React from 'react';
5
+ import { Animated, View, Text, Pressable, LayoutAnimation } from 'react-native';
6
+ import { createStyleSheet, useStyles, useLoamTheme } from '@btndprojects/loam-theme-native';
7
+ import { jsxs, jsx } from 'react/jsx-runtime';
8
+
9
+ var DEFAULT_LABELS = {
10
+ dismiss: "Dismiss"
11
+ };
12
+ var TONE_ICON = {
13
+ info: "info",
14
+ good: "check-circle",
15
+ warn: "alert-triangle",
16
+ danger: "alert-circle",
17
+ neutral: "info"
18
+ };
19
+ function alertToneColors(theme, tone) {
20
+ switch (tone) {
21
+ case "good":
22
+ return {
23
+ glyph: theme.color.goodOnSoft,
24
+ border: theme.color.good,
25
+ tint: theme.color.goodSoft
26
+ };
27
+ case "warn":
28
+ return {
29
+ glyph: theme.color.warnOnSoft,
30
+ border: theme.color.warn,
31
+ tint: theme.color.warnSoft
32
+ };
33
+ case "danger":
34
+ return {
35
+ glyph: theme.color.dangerOnSoft,
36
+ border: theme.color.danger,
37
+ tint: theme.color.dangerSoft
38
+ };
39
+ case "neutral":
40
+ return {
41
+ glyph: theme.color.text2,
42
+ border: theme.color.borderStrong,
43
+ tint: theme.color.surface2
44
+ };
45
+ default:
46
+ return {
47
+ glyph: theme.color.infoOnSoft,
48
+ border: theme.color.info,
49
+ tint: theme.color.infoSoft
50
+ };
51
+ }
52
+ }
53
+ function Alert({
54
+ title,
55
+ description,
56
+ tone = "info",
57
+ icon,
58
+ dismissible = false,
59
+ onDismiss,
60
+ action,
61
+ children,
62
+ labels: labelsProp
63
+ }) {
64
+ const labels = useLabels("alert", DEFAULT_LABELS, labelsProp);
65
+ const { styles } = useStyles(sheet, { tone });
66
+ const theme = useLoamTheme("alert");
67
+ const toneColors = alertToneColors(theme, tone);
68
+ const showDismiss = dismissible || onDismiss != null;
69
+ const iconName = icon === false ? void 0 : icon ?? TONE_ICON[tone];
70
+ const dismissHitSlop = Math.max(0, Math.round((theme.tapMin - theme.icon.sm) / 2));
71
+ const level = useResolvedMotion(void 0, "alert");
72
+ const enter = React.useRef(new Animated.Value(level === "none" ? 1 : 0)).current;
73
+ React.useEffect(() => {
74
+ if (level === "none") return;
75
+ if (level === "reduced") {
76
+ Animated.timing(enter, { ...motionTiming(level), toValue: 1, useNativeDriver: true }).start();
77
+ return;
78
+ }
79
+ Animated.spring(enter, { ...springConfig(theme, "ds"), toValue: 1, useNativeDriver: true }).start();
80
+ }, []);
81
+ const dismiss = () => {
82
+ if (level !== "none") {
83
+ LayoutAnimation.configureNext({
84
+ duration: theme.spring.ds.duration,
85
+ delete: { type: LayoutAnimation.Types.easeOut, property: LayoutAnimation.Properties.opacity },
86
+ update: level === "full" ? { type: LayoutAnimation.Types.spring, springDamping: theme.spring.ds.dampingRatio } : { type: LayoutAnimation.Types.easeOut }
87
+ });
88
+ }
89
+ onDismiss?.();
90
+ };
91
+ return /* @__PURE__ */ jsxs(
92
+ Animated.View,
93
+ {
94
+ accessibilityRole: "alert",
95
+ style: [
96
+ styles.base,
97
+ { borderColor: toneColors.border },
98
+ {
99
+ opacity: enter,
100
+ transform: level === "full" ? [{ translateY: enter.interpolate({ inputRange: [0, 1], outputRange: [4, 0] }) }] : []
101
+ }
102
+ ],
103
+ children: [
104
+ iconName ? /* @__PURE__ */ jsx(View, { style: styles.iconSlot, children: /* @__PURE__ */ jsx(Icon, { name: iconName, size: theme.icon.md, color: toneColors.glyph }) }) : null,
105
+ /* @__PURE__ */ jsxs(View, { style: styles.content, children: [
106
+ /* @__PURE__ */ jsx(Text, { style: styles.title, children: title }),
107
+ description ? /* @__PURE__ */ jsx(Text, { style: styles.description, children: description }) : null,
108
+ children,
109
+ action ? /* @__PURE__ */ jsx(View, { style: styles.action, children: action }) : null
110
+ ] }),
111
+ showDismiss ? /* @__PURE__ */ jsx(
112
+ Pressable,
113
+ {
114
+ accessibilityRole: "button",
115
+ accessibilityLabel: labels.dismiss,
116
+ onPress: dismiss,
117
+ hitSlop: dismissHitSlop,
118
+ style: ({ pressed }) => [styles.dismiss, pressed ? styles.pressed : null],
119
+ children: /* @__PURE__ */ jsx(Icon, { name: "x", size: theme.icon.sm, color: toneColors.glyph })
120
+ }
121
+ ) : null
122
+ ]
123
+ }
124
+ );
125
+ }
126
+ var sheet = createStyleSheet((theme) => ({
127
+ base: {
128
+ flexDirection: "row",
129
+ alignItems: "flex-start",
130
+ gap: theme.space.s3,
131
+ padding: theme.space.s4,
132
+ borderRadius: theme.radius.lg,
133
+ borderWidth: theme.borderWidth.thin,
134
+ variants: {
135
+ tone: {
136
+ info: { backgroundColor: theme.color.infoSoft },
137
+ good: { backgroundColor: theme.color.goodSoft },
138
+ warn: { backgroundColor: theme.color.warnSoft },
139
+ danger: { backgroundColor: theme.color.dangerSoft },
140
+ neutral: { backgroundColor: theme.color.surface2 }
141
+ }
142
+ }
143
+ },
144
+ iconSlot: {
145
+ // Nudge the icon onto the title's optical baseline.
146
+ paddingTop: theme.space[1]
147
+ },
148
+ content: {
149
+ flex: 1,
150
+ gap: theme.space.s1
151
+ },
152
+ title: {
153
+ fontFamily: theme.font.sans,
154
+ fontWeight: theme.fontWeight.bold,
155
+ fontSize: theme.fontSize[14],
156
+ color: theme.color.text
157
+ },
158
+ description: {
159
+ fontFamily: theme.font.sans,
160
+ fontSize: theme.fontSize[14],
161
+ color: theme.color.text
162
+ },
163
+ action: {
164
+ flexDirection: "row",
165
+ alignItems: "center",
166
+ gap: theme.space.s2,
167
+ marginTop: theme.space.s2
168
+ },
169
+ pressed: { opacity: theme.state.pressedOpacity },
170
+ // `marginStart`, not `marginLeft`: RN's layout engine mirrors it under RTL.
171
+ dismiss: {
172
+ marginStart: theme.space.s2
173
+ }
174
+ }));
175
+
176
+ export { Alert };
@@ -1,6 +1,8 @@
1
- import { Icon } from './chunk-TKVFVF5D.js';
1
+ import { useLabels } from './chunk-APCWFOZW.js';
2
+ import { Icon } from './chunk-UXGIW7OK.js';
3
+ import { springConfig, motionTiming } from './chunk-J64KGCGX.js';
2
4
  import * as React from 'react';
3
- import { Animated, Easing, Pressable, Text, View } from 'react-native';
5
+ import { Animated, Pressable, Text, View, LayoutAnimation } from 'react-native';
4
6
  import { createStyleSheet, useStyles, useLoamTheme } from '@btndprojects/loam-theme-native';
5
7
  import { jsx, jsxs } from 'react/jsx-runtime';
6
8
 
@@ -60,6 +62,12 @@ var SPEC = {
60
62
  systemDismissInsetY: -9,
61
63
  systemDismissInsetEnd: -13
62
64
  };
65
+ var DEFAULT_LABELS = {
66
+ dismiss: "Dismiss",
67
+ refresh: "Refresh",
68
+ updated: (when) => `Updated ${when}`,
69
+ windowInZone: (timeWindow, timezone) => `${timeWindow} \xB7 ${timezone}`
70
+ };
63
71
  var TONE_ICON = {
64
72
  info: "info",
65
73
  success: "check-circle",
@@ -73,7 +81,7 @@ var VARIANT_META = {
73
81
  maintenance: { tone: "info", icon: "wrench" }
74
82
  };
75
83
  function useToneColor(tone) {
76
- const theme = useLoamTheme();
84
+ const theme = useLoamTheme("banner");
77
85
  switch (tone) {
78
86
  case "success":
79
87
  return theme.color.goodOnSoft;
@@ -105,42 +113,50 @@ function Banner({
105
113
  onDismiss,
106
114
  updatedLabel,
107
115
  onRefresh,
108
- refreshLabel = "Refresh",
116
+ refreshLabel: refreshLabelProp,
109
117
  timeWindow,
110
118
  timezone,
111
119
  countdown,
112
- motion = "full"
120
+ motion = "full",
121
+ labels: labelsProp
113
122
  }) {
123
+ const labels = useLabels("banner", DEFAULT_LABELS, labelsProp);
124
+ const refreshLabel = refreshLabelProp ?? labels.refresh;
114
125
  const variantMeta = variant === "default" ? void 0 : VARIANT_META[variant];
115
126
  const effectiveTone = tone ?? variantMeta?.tone ?? "info";
116
127
  const { styles } = useStyles(sheet, { tone: effectiveTone, placement });
117
- const theme = useLoamTheme();
128
+ const theme = useLoamTheme("banner");
118
129
  const toneColor = useToneColor(effectiveTone);
119
130
  const borderColor = toneColor + "55";
120
131
  const iconName = icon ?? variantMeta?.icon ?? TONE_ICON[effectiveTone];
121
132
  const actionPos = actionLabel ? resolvePlacement(actionPlacement, actionLabel) : void 0;
122
133
  const dismissible = variant !== "offline" && Boolean(onDismiss);
123
134
  const showRefresh = !actionLabel && Boolean(onRefresh);
124
- const metaLine = variant === "stale" && updatedLabel ? `Updated ${updatedLabel}` : variant === "maintenance" && timeWindow ? timezone ? `${timeWindow} \xB7 ${timezone}` : timeWindow : null;
135
+ const metaLine = variant === "stale" && updatedLabel ? labels.updated(updatedLabel) : variant === "maintenance" && timeWindow ? timezone ? labels.windowInZone(timeWindow, timezone) : timeWindow : null;
125
136
  const actionHitSlop = Math.max(0, Math.round((theme.tapMin - SPEC.actionMinHeight) / 2));
126
137
  const dismissHitSlop = Math.max(0, Math.round((theme.tapMin - SPEC.glyph) / 2));
127
138
  const refreshHitSlop = Math.max(0, Math.round((theme.tapMin - SPEC.refreshMinHeight) / 2));
128
139
  const animate = motion === "full" && !theme.reduceMotion;
129
- const opacity = React.useRef(new Animated.Value(animate ? 0 : 1)).current;
140
+ const opacity = React.useRef(new Animated.Value(motion === "none" ? 1 : 0)).current;
130
141
  React.useEffect(() => {
131
- if (!animate) {
142
+ if (motion === "none") {
132
143
  opacity.setValue(1);
133
144
  return;
134
145
  }
135
- const anim = Animated.timing(opacity, {
136
- toValue: 1,
137
- duration: theme.motion.enter.duration,
138
- easing: Easing.bezier(...theme.motion.enter.easing),
139
- useNativeDriver: true
140
- });
146
+ const anim = animate ? Animated.spring(opacity, { ...springConfig(theme, "ds"), toValue: 1, useNativeDriver: true }) : Animated.timing(opacity, { ...motionTiming("reduced"), toValue: 1, useNativeDriver: true });
141
147
  anim.start();
142
148
  return () => anim.stop();
143
- }, [animate, opacity, theme.motion.enter.duration, theme.motion.enter.easing]);
149
+ }, []);
150
+ const close = () => {
151
+ if (motion !== "none") {
152
+ LayoutAnimation.configureNext({
153
+ duration: theme.spring.de.duration,
154
+ update: animate ? { type: LayoutAnimation.Types.spring, springDamping: theme.spring.ds.dampingRatio } : { type: LayoutAnimation.Types.easeOut },
155
+ delete: { type: LayoutAnimation.Types.easeOut, property: LayoutAnimation.Properties.opacity }
156
+ });
157
+ }
158
+ onDismiss?.();
159
+ };
144
160
  const action = actionLabel && actionPos ? /* @__PURE__ */ jsx(
145
161
  Pressable,
146
162
  {
@@ -148,7 +164,10 @@ function Banner({
148
164
  accessibilityLabel: actionLabel,
149
165
  onPress: onAction,
150
166
  hitSlop: actionHitSlop,
151
- style: actionPos === "inline" ? styles.actionInline : styles.action,
167
+ style: ({ pressed }) => [
168
+ actionPos === "inline" ? styles.actionInline : styles.action,
169
+ pressed ? styles.pressed : null
170
+ ],
152
171
  children: /* @__PURE__ */ jsx(Text, { style: [styles.actionLabel, { color: toneColor }], children: actionLabel })
153
172
  }
154
173
  ) : null;
@@ -159,14 +178,25 @@ function Banner({
159
178
  accessibilityLabel: refreshLabel,
160
179
  onPress: onRefresh,
161
180
  hitSlop: refreshHitSlop,
162
- style: [styles.refresh, { borderColor: toneColor }],
181
+ style: ({ pressed }) => [
182
+ styles.refresh,
183
+ { borderColor: toneColor },
184
+ pressed ? styles.pressed : null
185
+ ],
163
186
  children: [
164
187
  /* @__PURE__ */ jsx(Icon, { name: "refresh", size: SPEC.refreshGlyph, color: toneColor }),
165
188
  /* @__PURE__ */ jsx(Text, { style: [styles.actionLabel, { color: toneColor }], children: refreshLabel })
166
189
  ]
167
190
  }
168
191
  ) : null;
169
- return /* @__PURE__ */ jsxs(Animated.View, { accessibilityRole: "alert", style: [styles.base, { borderColor, opacity }], children: [
192
+ return /* @__PURE__ */ jsxs(Animated.View, { accessibilityRole: "alert", style: [
193
+ styles.base,
194
+ {
195
+ borderColor,
196
+ opacity,
197
+ transform: animate ? [{ translateY: opacity.interpolate({ inputRange: [0, 1], outputRange: [-8, 0] }) }] : []
198
+ }
199
+ ], children: [
170
200
  /* @__PURE__ */ jsx(View, { style: styles.iconSlot, children: /* @__PURE__ */ jsx(Icon, { name: iconName, size: SPEC.glyph, color: toneColor }) }),
171
201
  /* @__PURE__ */ jsxs(View, { style: styles.content, children: [
172
202
  title ? /* @__PURE__ */ jsx(Text, { style: styles.title, children: title }) : null,
@@ -181,10 +211,10 @@ function Banner({
181
211
  Pressable,
182
212
  {
183
213
  accessibilityRole: "button",
184
- accessibilityLabel: "Dismiss",
185
- onPress: onDismiss,
214
+ accessibilityLabel: labels.dismiss,
215
+ onPress: close,
186
216
  hitSlop: dismissHitSlop,
187
- style: styles.dismiss,
217
+ style: ({ pressed }) => [styles.dismiss, pressed ? styles.pressed : null],
188
218
  children: /* @__PURE__ */ jsx(Icon, { name: "x", size: SPEC.glyph, color: toneColor })
189
219
  }
190
220
  ) : null
@@ -193,10 +223,12 @@ function Banner({
193
223
  function SystemBanner({
194
224
  message,
195
225
  icon = "star",
196
- onDismiss
226
+ onDismiss,
227
+ labels: labelsProp
197
228
  }) {
229
+ const labels = useLabels("banner", DEFAULT_LABELS, labelsProp);
198
230
  const { styles } = useStyles(sheet);
199
- const theme = useLoamTheme();
231
+ const theme = useLoamTheme("banner");
200
232
  return /* @__PURE__ */ jsxs(View, { accessibilityRole: "alert", style: styles.system, children: [
201
233
  /* @__PURE__ */ jsx(Icon, { name: icon, size: 18, color: theme.color.accentInk }),
202
234
  /* @__PURE__ */ jsx(Text, { style: styles.systemMessage, numberOfLines: 1, ellipsizeMode: "tail", children: message }),
@@ -204,9 +236,9 @@ function SystemBanner({
204
236
  Pressable,
205
237
  {
206
238
  accessibilityRole: "button",
207
- accessibilityLabel: "Dismiss",
239
+ accessibilityLabel: labels.dismiss,
208
240
  onPress: onDismiss,
209
- style: styles.systemDismiss,
241
+ style: ({ pressed }) => [styles.systemDismiss, pressed ? styles.pressed : null],
210
242
  children: /* @__PURE__ */ jsx(Icon, { name: "x", size: SPEC.systemGlyph, color: theme.color.accentInk })
211
243
  }
212
244
  ) : null
@@ -342,6 +374,8 @@ var sheet = createStyleSheet((theme) => ({
342
374
  borderWidth: theme.borderWidth.thin,
343
375
  backgroundColor: "transparent"
344
376
  },
377
+ // Press acknowledgement for the unboxed controls: a dim, no layout change.
378
+ pressed: { opacity: theme.state.pressedOpacity },
345
379
  dismiss: {
346
380
  paddingTop: theme.space[1]
347
381
  },