@lt-three/love3 0.0.0 → 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 (377) hide show
  1. package/README.md +85 -1
  2. package/dist/native/analytics/animation.d.ts +4 -0
  3. package/dist/native/analytics/animation.js +6 -0
  4. package/dist/native/analytics/chart.types.d.ts +25 -0
  5. package/dist/native/analytics/chart.types.js +0 -0
  6. package/dist/native/analytics/line-chart.d.ts +4 -0
  7. package/dist/native/analytics/line-chart.ios.d.ts +4 -0
  8. package/dist/native/analytics/line-chart.ios.js +24 -0
  9. package/dist/native/analytics/line-chart.js +33 -0
  10. package/dist/native/analytics/metric-card.d.ts +10 -0
  11. package/dist/native/analytics/metric-card.js +29 -0
  12. package/dist/native/analytics/multi-line-chart.d.ts +18 -0
  13. package/dist/native/analytics/multi-line-chart.js +216 -0
  14. package/dist/native/analytics/pie-chart.d.ts +15 -0
  15. package/dist/native/analytics/pie-chart.ios.d.ts +4 -0
  16. package/dist/native/analytics/pie-chart.ios.js +24 -0
  17. package/dist/native/analytics/pie-chart.js +92 -0
  18. package/dist/native/analytics/single-number.d.ts +19 -0
  19. package/dist/native/analytics/single-number.js +101 -0
  20. package/dist/native/atom/avatar.d.ts +21 -0
  21. package/dist/native/atom/avatar.js +46 -0
  22. package/dist/native/atom/badge.d.ts +28 -0
  23. package/dist/native/atom/badge.js +51 -0
  24. package/dist/native/atom/button.d.ts +46 -0
  25. package/dist/native/atom/button.js +109 -0
  26. package/dist/native/atom/checkbox.d.ts +21 -0
  27. package/dist/native/atom/checkbox.js +47 -0
  28. package/dist/native/atom/colored-value.d.ts +12 -0
  29. package/dist/native/atom/colored-value.js +24 -0
  30. package/dist/native/atom/image.d.ts +21 -0
  31. package/dist/native/atom/image.js +72 -0
  32. package/dist/native/atom/label.d.ts +18 -0
  33. package/dist/native/atom/label.js +33 -0
  34. package/dist/native/atom/link.d.ts +18 -0
  35. package/dist/native/atom/link.js +25 -0
  36. package/dist/native/atom/readout.d.ts +22 -0
  37. package/dist/native/atom/readout.js +39 -0
  38. package/dist/native/atom/search-input.d.ts +12 -0
  39. package/dist/native/atom/search-input.js +36 -0
  40. package/dist/native/atom/select.d.ts +54 -0
  41. package/dist/native/atom/select.js +200 -0
  42. package/dist/native/atom/separator.d.ts +12 -0
  43. package/dist/native/atom/separator.js +16 -0
  44. package/dist/native/atom/skeleton.d.ts +12 -0
  45. package/dist/native/atom/skeleton.js +39 -0
  46. package/dist/native/atom/slider.d.ts +32 -0
  47. package/dist/native/atom/slider.js +75 -0
  48. package/dist/native/atom/spinner.d.ts +15 -0
  49. package/dist/native/atom/spinner.js +25 -0
  50. package/dist/native/atom/switch.d.ts +18 -0
  51. package/dist/native/atom/switch.js +52 -0
  52. package/dist/native/atom/symbol.d.ts +16 -0
  53. package/dist/native/atom/symbol.js +38 -0
  54. package/dist/native/atom/symbol.types.d.ts +25 -0
  55. package/dist/native/atom/symbol.types.js +49 -0
  56. package/dist/native/atom/text-field.d.ts +49 -0
  57. package/dist/native/atom/text-field.js +56 -0
  58. package/dist/native/atom/text.d.ts +2 -0
  59. package/dist/native/atom/text.js +3 -0
  60. package/dist/native/atom/theme-toggle.d.ts +21 -0
  61. package/dist/native/atom/theme-toggle.js +36 -0
  62. package/dist/native/atom/timezone-select.d.ts +16 -0
  63. package/dist/native/atom/timezone-select.js +28 -0
  64. package/dist/native/atom/typography.d.ts +13 -0
  65. package/dist/native/atom/typography.js +28 -0
  66. package/dist/native/base/button.d.ts +61 -0
  67. package/dist/native/base/button.js +92 -0
  68. package/dist/native/base/form.d.ts +72 -0
  69. package/dist/native/base/form.js +113 -0
  70. package/dist/native/base/glass-card.d.ts +15 -0
  71. package/dist/native/base/glass-card.js +38 -0
  72. package/dist/native/base/input.d.ts +29 -0
  73. package/dist/native/base/input.js +27 -0
  74. package/dist/native/base/sheet.d.ts +71 -0
  75. package/dist/native/base/sheet.js +187 -0
  76. package/dist/native/base/text.d.ts +14 -0
  77. package/dist/native/base/text.js +53 -0
  78. package/dist/native/form/checkbox.d.ts +13 -0
  79. package/dist/native/form/checkbox.js +55 -0
  80. package/dist/native/form/date-picker.d.ts +23 -0
  81. package/dist/native/form/date-picker.js +119 -0
  82. package/dist/native/form/form.d.ts +22 -0
  83. package/dist/native/form/form.js +44 -0
  84. package/dist/native/form/radio-group.d.ts +23 -0
  85. package/dist/native/form/radio-group.js +88 -0
  86. package/dist/native/form/select.d.ts +13 -0
  87. package/dist/native/form/select.js +45 -0
  88. package/dist/native/form/slider.d.ts +14 -0
  89. package/dist/native/form/slider.js +42 -0
  90. package/dist/native/form/switch.d.ts +9 -0
  91. package/dist/native/form/switch.js +59 -0
  92. package/dist/native/form/text-area.d.ts +11 -0
  93. package/dist/native/form/text-area.js +50 -0
  94. package/dist/native/form/text-input.d.ts +18 -0
  95. package/dist/native/form/text-input.js +90 -0
  96. package/dist/native/index.d.ts +1 -0
  97. package/dist/native/index.js +0 -0
  98. package/dist/native/layout/accordion.d.ts +25 -0
  99. package/dist/native/layout/accordion.js +54 -0
  100. package/dist/native/layout/card.d.ts +47 -0
  101. package/dist/native/layout/card.js +57 -0
  102. package/dist/native/layout/description.d.ts +16 -0
  103. package/dist/native/layout/description.js +32 -0
  104. package/dist/native/layout/error.d.ts +21 -0
  105. package/dist/native/layout/error.js +44 -0
  106. package/dist/native/layout/information.d.ts +25 -0
  107. package/dist/native/layout/information.js +35 -0
  108. package/dist/native/layout/locked.d.ts +38 -0
  109. package/dist/native/layout/locked.js +94 -0
  110. package/dist/native/layout/modal.d.ts +25 -0
  111. package/dist/native/layout/modal.js +93 -0
  112. package/dist/native/layout/not-found.d.ts +17 -0
  113. package/dist/native/layout/not-found.js +30 -0
  114. package/dist/native/layout/page-frame.d.ts +23 -0
  115. package/dist/native/layout/page-frame.js +46 -0
  116. package/dist/native/layout/panel.d.ts +18 -0
  117. package/dist/native/layout/panel.js +23 -0
  118. package/dist/native/layout/reorderable-list.d.ts +42 -0
  119. package/dist/native/layout/reorderable-list.js +52 -0
  120. package/dist/native/layout/sheet.d.ts +30 -0
  121. package/dist/native/layout/sheet.js +46 -0
  122. package/dist/native/layout/simple-dialog.d.ts +16 -0
  123. package/dist/native/layout/simple-dialog.js +20 -0
  124. package/dist/native/layout/simple-table.d.ts +50 -0
  125. package/dist/native/layout/simple-table.js +75 -0
  126. package/dist/native/layout/tab-bar.d.ts +33 -0
  127. package/dist/native/layout/tab-bar.js +48 -0
  128. package/dist/native/layout/tabs.d.ts +28 -0
  129. package/dist/native/layout/tabs.js +54 -0
  130. package/dist/native/layout/tuning-panel.d.ts +24 -0
  131. package/dist/native/layout/tuning-panel.js +246 -0
  132. package/dist/native/lib/autocomplete.d.ts +7 -0
  133. package/dist/native/lib/autocomplete.js +34 -0
  134. package/dist/native/lib/breakpoints.d.ts +14 -0
  135. package/dist/native/lib/breakpoints.js +17 -0
  136. package/dist/native/lib/chart-palette.d.ts +8 -0
  137. package/dist/native/lib/chart-palette.js +20 -0
  138. package/dist/native/lib/confirm.d.ts +48 -0
  139. package/dist/native/lib/confirm.js +69 -0
  140. package/dist/native/lib/control.d.ts +24 -0
  141. package/dist/native/lib/control.js +0 -0
  142. package/dist/native/lib/external-store.d.ts +16 -0
  143. package/dist/native/lib/external-store.js +30 -0
  144. package/dist/native/lib/keyboard.d.ts +15 -0
  145. package/dist/native/lib/keyboard.js +24 -0
  146. package/dist/native/lib/labels.d.ts +15 -0
  147. package/dist/native/lib/labels.js +17 -0
  148. package/dist/native/lib/loading.d.ts +10 -0
  149. package/dist/native/lib/loading.js +15 -0
  150. package/dist/native/lib/network.d.ts +11 -0
  151. package/dist/native/lib/network.js +20 -0
  152. package/dist/native/lib/scheme.d.ts +18 -0
  153. package/dist/native/lib/scheme.js +22 -0
  154. package/dist/native/lib/snackbar.d.ts +45 -0
  155. package/dist/native/lib/snackbar.js +59 -0
  156. package/dist/native/lib/theme.d.ts +34 -0
  157. package/dist/native/lib/theme.js +53 -0
  158. package/dist/native/lib/timezone.d.ts +26 -0
  159. package/dist/native/lib/timezone.js +95 -0
  160. package/dist/native/lib/token-color.d.ts +5 -0
  161. package/dist/native/lib/token-color.js +13 -0
  162. package/dist/native/lib/token-color.web.d.ts +4 -0
  163. package/dist/native/lib/token-color.web.js +7 -0
  164. package/dist/native/lib/tuning-context.d.ts +9 -0
  165. package/dist/native/lib/tuning-context.js +7 -0
  166. package/dist/native/lib/tuning.d.ts +24 -0
  167. package/dist/native/lib/tuning.js +42 -0
  168. package/dist/native/lib/typography.d.ts +10 -0
  169. package/dist/native/lib/typography.js +11 -0
  170. package/dist/native/lib/utils.d.ts +11 -0
  171. package/dist/native/lib/utils.js +21 -0
  172. package/dist/native/once/confirm.d.ts +7 -0
  173. package/dist/native/once/confirm.js +60 -0
  174. package/dist/native/once/error-boundary.d.ts +28 -0
  175. package/dist/native/once/error-boundary.js +55 -0
  176. package/dist/native/once/loading-lock.d.ts +8 -0
  177. package/dist/native/once/loading-lock.js +28 -0
  178. package/dist/native/once/offline-banner.d.ts +15 -0
  179. package/dist/native/once/offline-banner.js +35 -0
  180. package/dist/native/once/snackbar.d.ts +17 -0
  181. package/dist/native/once/snackbar.js +106 -0
  182. package/dist/native/styles.css +46 -0
  183. package/dist/shared/analytics.d.ts +71 -0
  184. package/dist/shared/analytics.js +0 -0
  185. package/dist/shared/button.d.ts +7 -0
  186. package/dist/shared/button.js +23 -0
  187. package/dist/shared/form.d.ts +45 -0
  188. package/dist/shared/form.js +46 -0
  189. package/dist/shared/index.d.ts +3 -0
  190. package/dist/shared/index.js +3 -0
  191. package/dist/tokens/contrast-pairs.d.ts +30 -0
  192. package/dist/tokens/contrast-pairs.js +404 -0
  193. package/dist/tokens/index.d.ts +6 -0
  194. package/dist/tokens/index.js +10 -0
  195. package/dist/tokens/styles.gen.css +250 -0
  196. package/dist/tokens/tokens.gen.d.ts +141 -0
  197. package/dist/tokens/tokens.gen.js +206 -0
  198. package/dist/tuning/catalog.d.ts +27 -0
  199. package/dist/tuning/catalog.gen.d.ts +4 -0
  200. package/dist/tuning/catalog.gen.js +397 -0
  201. package/dist/tuning/catalog.js +128 -0
  202. package/dist/tuning/color.d.ts +20 -0
  203. package/dist/tuning/color.js +80 -0
  204. package/dist/tuning/css.d.ts +35 -0
  205. package/dist/tuning/css.js +147 -0
  206. package/dist/tuning/index.d.ts +8 -0
  207. package/dist/tuning/index.js +9 -0
  208. package/dist/tuning/model.d.ts +33 -0
  209. package/dist/tuning/model.js +154 -0
  210. package/dist/tuning/native.d.ts +35 -0
  211. package/dist/tuning/native.js +80 -0
  212. package/dist/tuning/schema.d.ts +69 -0
  213. package/dist/tuning/schema.js +247 -0
  214. package/dist/tuning/types.d.ts +75 -0
  215. package/dist/tuning/types.js +39 -0
  216. package/dist/web/analytics/line-chart.d.ts +20 -0
  217. package/dist/web/analytics/line-chart.js +28 -0
  218. package/dist/web/analytics/metric-card.d.ts +18 -0
  219. package/dist/web/analytics/metric-card.js +40 -0
  220. package/dist/web/analytics/multi-line-chart.d.ts +39 -0
  221. package/dist/web/analytics/multi-line-chart.js +345 -0
  222. package/dist/web/atom/avatar.d.ts +11 -0
  223. package/dist/web/atom/avatar.js +24 -0
  224. package/dist/web/atom/badge.d.ts +2 -0
  225. package/dist/web/atom/badge.js +3 -0
  226. package/dist/web/atom/button.d.ts +23 -0
  227. package/dist/web/atom/button.js +35 -0
  228. package/dist/web/atom/checkbox.d.ts +19 -0
  229. package/dist/web/atom/checkbox.js +33 -0
  230. package/dist/web/atom/colored-value.d.ts +13 -0
  231. package/dist/web/atom/colored-value.js +24 -0
  232. package/dist/web/atom/help.d.ts +10 -0
  233. package/dist/web/atom/help.js +18 -0
  234. package/dist/web/atom/label.d.ts +2 -0
  235. package/dist/web/atom/label.js +3 -0
  236. package/dist/web/atom/segmented-control.d.ts +39 -0
  237. package/dist/web/atom/segmented-control.js +42 -0
  238. package/dist/web/atom/select.d.ts +43 -0
  239. package/dist/web/atom/select.js +93 -0
  240. package/dist/web/atom/separator.d.ts +2 -0
  241. package/dist/web/atom/separator.js +3 -0
  242. package/dist/web/atom/skeleton.d.ts +2 -0
  243. package/dist/web/atom/skeleton.js +3 -0
  244. package/dist/web/atom/slider.d.ts +33 -0
  245. package/dist/web/atom/slider.js +70 -0
  246. package/dist/web/atom/spinner.d.ts +8 -0
  247. package/dist/web/atom/spinner.js +14 -0
  248. package/dist/web/atom/switch.d.ts +11 -0
  249. package/dist/web/atom/switch.js +10 -0
  250. package/dist/web/atom/text-area.d.ts +23 -0
  251. package/dist/web/atom/text-area.js +27 -0
  252. package/dist/web/atom/text-field.d.ts +18 -0
  253. package/dist/web/atom/text-field.js +22 -0
  254. package/dist/web/atom/toggle-chip.d.ts +22 -0
  255. package/dist/web/atom/toggle-chip.js +28 -0
  256. package/dist/web/atom/tooltip.d.ts +23 -0
  257. package/dist/web/atom/tooltip.js +26 -0
  258. package/dist/web/atom/typography.d.ts +6 -0
  259. package/dist/web/atom/typography.js +23 -0
  260. package/dist/web/base/accordion.d.ts +9 -0
  261. package/dist/web/base/accordion.js +44 -0
  262. package/dist/web/base/alert.d.ts +11 -0
  263. package/dist/web/base/alert.js +37 -0
  264. package/dist/web/base/avatar.d.ts +8 -0
  265. package/dist/web/base/avatar.js +29 -0
  266. package/dist/web/base/badge.d.ts +12 -0
  267. package/dist/web/base/badge.js +26 -0
  268. package/dist/web/base/breadcrumb.d.ts +16 -0
  269. package/dist/web/base/breadcrumb.js +72 -0
  270. package/dist/web/base/button.d.ts +12 -0
  271. package/dist/web/base/button.js +47 -0
  272. package/dist/web/base/card.d.ts +19 -0
  273. package/dist/web/base/card.js +74 -0
  274. package/dist/web/base/checkbox.d.ts +6 -0
  275. package/dist/web/base/checkbox.js +21 -0
  276. package/dist/web/base/dialog.d.ts +20 -0
  277. package/dist/web/base/dialog.js +92 -0
  278. package/dist/web/base/dropdown-menu.d.ts +29 -0
  279. package/dist/web/base/dropdown-menu.js +125 -0
  280. package/dist/web/base/field.d.ts +27 -0
  281. package/dist/web/base/field.js +118 -0
  282. package/dist/web/base/form.d.ts +38 -0
  283. package/dist/web/base/form.js +110 -0
  284. package/dist/web/base/input.d.ts +9 -0
  285. package/dist/web/base/input.js +23 -0
  286. package/dist/web/base/label.d.ts +6 -0
  287. package/dist/web/base/label.js +15 -0
  288. package/dist/web/base/pagination.d.ts +34 -0
  289. package/dist/web/base/pagination.js +90 -0
  290. package/dist/web/base/popover.d.ts +11 -0
  291. package/dist/web/base/popover.js +37 -0
  292. package/dist/web/base/radio-group.d.ts +7 -0
  293. package/dist/web/base/radio-group.js +27 -0
  294. package/dist/web/base/scroll-area.d.ts +10 -0
  295. package/dist/web/base/scroll-area.js +41 -0
  296. package/dist/web/base/select.d.ts +17 -0
  297. package/dist/web/base/select.js +96 -0
  298. package/dist/web/base/separator.d.ts +6 -0
  299. package/dist/web/base/separator.js +17 -0
  300. package/dist/web/base/sheet.d.ts +19 -0
  301. package/dist/web/base/sheet.js +88 -0
  302. package/dist/web/base/skeleton.d.ts +5 -0
  303. package/dist/web/base/skeleton.js +14 -0
  304. package/dist/web/base/slider.d.ts +9 -0
  305. package/dist/web/base/slider.js +39 -0
  306. package/dist/web/base/sonner.d.ts +9 -0
  307. package/dist/web/base/sonner.js +25 -0
  308. package/dist/web/base/spinner.d.ts +5 -0
  309. package/dist/web/base/spinner.js +17 -0
  310. package/dist/web/base/switch.d.ts +6 -0
  311. package/dist/web/base/switch.js +19 -0
  312. package/dist/web/base/table.d.ts +14 -0
  313. package/dist/web/base/table.js +68 -0
  314. package/dist/web/base/tabs.d.ts +9 -0
  315. package/dist/web/base/tabs.js +36 -0
  316. package/dist/web/base/textarea.d.ts +9 -0
  317. package/dist/web/base/textarea.js +23 -0
  318. package/dist/web/base/tooltip.d.ts +9 -0
  319. package/dist/web/base/tooltip.js +36 -0
  320. package/dist/web/form/checkbox.d.ts +35 -0
  321. package/dist/web/form/checkbox.js +91 -0
  322. package/dist/web/form/radio-group.d.ts +24 -0
  323. package/dist/web/form/radio-group.js +75 -0
  324. package/dist/web/form/select.d.ts +16 -0
  325. package/dist/web/form/select.js +44 -0
  326. package/dist/web/form/slider.d.ts +19 -0
  327. package/dist/web/form/slider.js +51 -0
  328. package/dist/web/form/switch.d.ts +11 -0
  329. package/dist/web/form/switch.js +50 -0
  330. package/dist/web/form/text-area.d.ts +10 -0
  331. package/dist/web/form/text-area.js +31 -0
  332. package/dist/web/form/text-input.d.ts +10 -0
  333. package/dist/web/form/text-input.js +42 -0
  334. package/dist/web/index.d.ts +1 -0
  335. package/dist/web/index.js +0 -0
  336. package/dist/web/layout/accordion.d.ts +26 -0
  337. package/dist/web/layout/accordion.js +29 -0
  338. package/dist/web/layout/alert-modal.d.ts +41 -0
  339. package/dist/web/layout/alert-modal.js +71 -0
  340. package/dist/web/layout/card.d.ts +17 -0
  341. package/dist/web/layout/card.js +35 -0
  342. package/dist/web/layout/description.d.ts +12 -0
  343. package/dist/web/layout/description.js +20 -0
  344. package/dist/web/layout/information.d.ts +36 -0
  345. package/dist/web/layout/information.js +53 -0
  346. package/dist/web/layout/modal.d.ts +16 -0
  347. package/dist/web/layout/modal.js +37 -0
  348. package/dist/web/layout/page-frame.d.ts +37 -0
  349. package/dist/web/layout/page-frame.js +79 -0
  350. package/dist/web/layout/scroll-area.d.ts +10 -0
  351. package/dist/web/layout/scroll-area.js +13 -0
  352. package/dist/web/layout/sheet.d.ts +32 -0
  353. package/dist/web/layout/sheet.js +68 -0
  354. package/dist/web/layout/simple-dialog.d.ts +11 -0
  355. package/dist/web/layout/simple-dialog.js +24 -0
  356. package/dist/web/layout/simple-table.d.ts +49 -0
  357. package/dist/web/layout/simple-table.js +58 -0
  358. package/dist/web/layout/tabs.d.ts +26 -0
  359. package/dist/web/layout/tabs.js +42 -0
  360. package/dist/web/layout/titled-modal.d.ts +32 -0
  361. package/dist/web/layout/titled-modal.js +58 -0
  362. package/dist/web/lib/css-vars.d.ts +14 -0
  363. package/dist/web/lib/css-vars.js +18 -0
  364. package/dist/web/lib/dialog.d.ts +13 -0
  365. package/dist/web/lib/dialog.js +0 -0
  366. package/dist/web/lib/form.d.ts +2 -0
  367. package/dist/web/lib/form.js +3 -0
  368. package/dist/web/lib/labels.d.ts +27 -0
  369. package/dist/web/lib/labels.js +29 -0
  370. package/dist/web/lib/modal-open-focus.d.ts +17 -0
  371. package/dist/web/lib/modal-open-focus.js +44 -0
  372. package/dist/web/lib/restore-focus.d.ts +12 -0
  373. package/dist/web/lib/restore-focus.js +32 -0
  374. package/dist/web/lib/utils.d.ts +4 -0
  375. package/dist/web/lib/utils.js +10 -0
  376. package/dist/web/styles.css +162 -0
  377. package/package.json +203 -4
@@ -0,0 +1,101 @@
1
+ import { useTokenColor } from "../lib/token-color.js";
2
+ import { cn } from "../lib/utils.js";
3
+ import { Text as Text$1 } from "../base/text.js";
4
+ import { tabularNums } from "../lib/typography.js";
5
+ import { View } from "react-native";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import Feather from "@expo/vector-icons/Feather";
8
+
9
+ //#region src/native/analytics/single-number.tsx
10
+ /**
11
+ * A metric showing a large number on a raised surface (surface corner radius, 1px hairline border).
12
+ * Mirrors the web analytics single-number. Increase/decrease uses the state colors (the surface does not invert, so the same theme values work).
13
+ */
14
+ function SingleNumber({ title, subTitle, value, unit, compareValue, compareTitle, reverseColor, className }) {
15
+ const up = useTokenColor("--state-success");
16
+ const down = useTokenColor("--state-error");
17
+ const diff = typeof compareValue === "number" ? (value ?? 0) - compareValue : 0;
18
+ const diffPercent = (1 - (value ?? 0) / (compareValue ?? 0)) * -100;
19
+ const diffColor = reverseColor ? diff < 0 ? up : down : diff < 0 ? down : up;
20
+ const iconName = diff < 0 ? "chevron-down" : "chevron-up";
21
+ const showCompare = typeof value === "number" && typeof compareValue === "number";
22
+ return /* @__PURE__ */ jsxs(View, {
23
+ className: cn("gap-3 rounded-surface border border-line bg-card p-3", className),
24
+ children: [
25
+ /* @__PURE__ */ jsxs(View, {
26
+ className: "flex-row items-end gap-2",
27
+ children: [/* @__PURE__ */ jsx(Text$1, {
28
+ className: "text-card-foreground text-lg font-bold",
29
+ children: title
30
+ }), subTitle ? /* @__PURE__ */ jsx(Text$1, {
31
+ className: "text-muted-foreground text-xs",
32
+ children: subTitle
33
+ }) : null]
34
+ }),
35
+ /* @__PURE__ */ jsxs(View, {
36
+ className: "flex-row items-end",
37
+ children: [/* @__PURE__ */ jsx(Text$1, {
38
+ style: tabularNums,
39
+ className: "text-card-foreground font-mono text-3xl leading-none",
40
+ children: value
41
+ }), unit ? /* @__PURE__ */ jsx(Text$1, {
42
+ className: "text-card-foreground ml-1 text-base",
43
+ children: unit
44
+ }) : null]
45
+ }),
46
+ showCompare ? /* @__PURE__ */ jsxs(View, {
47
+ className: "flex-row items-end gap-2",
48
+ children: [
49
+ /* @__PURE__ */ jsxs(View, {
50
+ className: "flex-row items-center",
51
+ children: [
52
+ /* @__PURE__ */ jsx(Feather, {
53
+ name: iconName,
54
+ size: 14,
55
+ color: diffColor
56
+ }),
57
+ /* @__PURE__ */ jsx(Text$1, {
58
+ style: [tabularNums, { color: diffColor }],
59
+ className: "font-mono text-lg leading-none",
60
+ children: diff
61
+ }),
62
+ unit ? /* @__PURE__ */ jsx(Text$1, {
63
+ style: { color: diffColor },
64
+ className: "ml-1 text-xs",
65
+ children: unit
66
+ }) : null
67
+ ]
68
+ }),
69
+ /* @__PURE__ */ jsxs(View, {
70
+ className: "flex-row items-center",
71
+ children: [
72
+ /* @__PURE__ */ jsx(Feather, {
73
+ name: iconName,
74
+ size: 14,
75
+ color: diffColor
76
+ }),
77
+ /* @__PURE__ */ jsx(Text$1, {
78
+ style: [tabularNums, { color: diffColor }],
79
+ className: "font-mono text-lg leading-none",
80
+ children: Number.isNaN(diffPercent) ? 0 : !Number.isFinite(diffPercent) ? 100 : diffPercent.toFixed(2)
81
+ }),
82
+ /* @__PURE__ */ jsx(Text$1, {
83
+ style: { color: diffColor },
84
+ className: "ml-1 text-xs",
85
+ children: "%"
86
+ })
87
+ ]
88
+ }),
89
+ compareTitle ? /* @__PURE__ */ jsx(Text$1, {
90
+ style: { color: diffColor },
91
+ className: "text-xs",
92
+ children: compareTitle
93
+ }) : null
94
+ ]
95
+ }) : null
96
+ ]
97
+ });
98
+ }
99
+
100
+ //#endregion
101
+ export { SingleNumber };
@@ -0,0 +1,21 @@
1
+ import { ReactElement } from "react";
2
+ //#region src/native/atom/avatar.d.ts
3
+ export type AvatarProps = {
4
+ src?: string;
5
+ /** Alternative text for the image. Empty by default (decorative; assumes a name is shown next to it). For a standalone face with no name, pass the person's name (same as the web) */
6
+ alt?: string;
7
+ /**
8
+ * What to show when there is no image or loading failed (initials, etc.). A string is wrapped in Text. **Omitted or empty shows a person icon**
9
+ * (the web shows nothing for an empty string). Numbers are not accepted (RN cannot render text directly under a View; pass a string).
10
+ */
11
+ fallback?: string | ReactElement;
12
+ /** Side length in px. Defaults to 24, the same as the web `size-6`. */
13
+ size?: number;
14
+ className?: string;
15
+ };
16
+ /**
17
+ * Same structure as the web atom/avatar (image + fallback).
18
+ * Drawn as a circle (`rounded-full`), like the web Avatar.
19
+ */
20
+ export declare function Avatar({ src, alt, fallback, size, className }: AvatarProps): import("react").JSX.Element;
21
+ //#endregion
@@ -0,0 +1,46 @@
1
+ import { useTokenColor } from "../lib/token-color.js";
2
+ import { cn } from "../lib/utils.js";
3
+ import { Text as Text$1 } from "../base/text.js";
4
+ import { useState } from "react";
5
+ import { View } from "react-native";
6
+ import { jsx } from "react/jsx-runtime";
7
+ import Feather from "@expo/vector-icons/Feather";
8
+ import { Image } from "expo-image";
9
+
10
+ //#region src/native/atom/avatar.tsx
11
+ /**
12
+ * Same structure as the web atom/avatar (image + fallback).
13
+ * Drawn as a circle (`rounded-full`), like the web Avatar.
14
+ */
15
+ function Avatar({ src, alt = "", fallback, size = 24, className }) {
16
+ const [failed, setFailed] = useState(false);
17
+ const wash = useTokenColor("--wash");
18
+ const showImage = !!src && !failed;
19
+ return /* @__PURE__ */ jsx(View, {
20
+ style: {
21
+ width: size,
22
+ height: size
23
+ },
24
+ className: cn("items-center justify-center overflow-hidden rounded-full bg-ink-500", className),
25
+ children: showImage ? /* @__PURE__ */ jsx(Image, {
26
+ source: { uri: src },
27
+ accessibilityLabel: alt,
28
+ style: {
29
+ width: size,
30
+ height: size
31
+ },
32
+ onError: () => setFailed(true)
33
+ }) : fallback === void 0 || fallback === "" ? /* @__PURE__ */ jsx(Feather, {
34
+ name: "user",
35
+ size: size * .6,
36
+ color: wash
37
+ }) : typeof fallback === "string" ? /* @__PURE__ */ jsx(Text$1, {
38
+ style: { fontSize: size * .45 },
39
+ className: "text-wash font-medium",
40
+ children: fallback
41
+ }) : fallback
42
+ });
43
+ }
44
+
45
+ //#endregion
46
+ export { Avatar };
@@ -0,0 +1,28 @@
1
+ import { ReactNode } from "react";
2
+ import { VariantProps } from "class-variance-authority";
3
+ //#region src/native/atom/badge.d.ts
4
+ declare const badgeVariants: (props?: ({
5
+ variant?: "<3" | "default" | "destructive" | "outline" | "secondary" | null | undefined;
6
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
+ export type BadgeVariants = VariantProps<typeof badgeVariants>["variant"];
8
+ export type BadgeProps = {
9
+ children: ReactNode;
10
+ variant?: BadgeVariants;
11
+ /**
12
+ * Makes the badge tappable (filter chips, etc.). A native-only addition not present in the web Badge;
13
+ * it keeps the look unchanged and secures a tap area equivalent to 44pt via `hitSlop`.
14
+ */
15
+ onPress?: () => void;
16
+ /**
17
+ * Name for screen readers and E2E. Always pass it when chips with the same text appear
18
+ * across different axes (to tell which axis a given "All" belongs to).
19
+ */
20
+ accessibilityLabel?: string;
21
+ /** Tells screen readers and E2E that this chip is selected. */
22
+ selected?: boolean;
23
+ className?: string;
24
+ textClassName?: string;
25
+ };
26
+ export declare function Badge({ children, variant, onPress, accessibilityLabel, selected, className, textClassName }: BadgeProps): import("react").JSX.Element;
27
+ //#endregion
28
+ export { badgeVariants };
@@ -0,0 +1,51 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { Text as Text$1 } from "../base/text.js";
3
+ import { tabularNums } from "../lib/typography.js";
4
+ import { Platform, Pressable, View } from "react-native";
5
+ import { jsx } from "react/jsx-runtime";
6
+ import { cva } from "class-variance-authority";
7
+
8
+ //#region src/native/atom/badge.tsx
9
+ const badgeVariants = cva("h-5 flex-row items-center justify-center gap-1 self-start rounded-control border px-1.5", {
10
+ variants: { variant: {
11
+ default: "border-transparent bg-action",
12
+ secondary: "border-transparent bg-secondary",
13
+ destructive: "border-state-error/30 bg-state-error/5",
14
+ outline: "border-line-strong",
15
+ "<3": "border-transparent bg-lt-three"
16
+ } },
17
+ defaultVariants: { variant: "default" }
18
+ });
19
+ const badgeTextVariants = cva("font-mono text-xs font-medium tracking-[0.01em]", {
20
+ variants: { variant: {
21
+ default: "text-action-foreground",
22
+ secondary: "text-secondary-foreground",
23
+ destructive: "text-state-error",
24
+ outline: "text-foreground",
25
+ "<3": "text-lt-three-foreground"
26
+ } },
27
+ defaultVariants: { variant: "default" }
28
+ });
29
+ function Badge({ children, variant, onPress, accessibilityLabel, selected, className, textClassName }) {
30
+ const badge = /* @__PURE__ */ jsx(View, {
31
+ className: cn(badgeVariants({ variant }), className),
32
+ children: typeof children === "string" || typeof children === "number" ? /* @__PURE__ */ jsx(Text$1, {
33
+ style: tabularNums,
34
+ className: cn(badgeTextVariants({ variant }), textClassName),
35
+ children
36
+ }) : children
37
+ });
38
+ if (!onPress) return badge;
39
+ return /* @__PURE__ */ jsx(Pressable, {
40
+ accessibilityRole: "button",
41
+ accessibilityLabel,
42
+ ...Platform.OS === "web" ? { "aria-pressed": selected } : { "aria-selected": selected },
43
+ onPress,
44
+ hitSlop: 12,
45
+ className: "self-start",
46
+ children: badge
47
+ });
48
+ }
49
+
50
+ //#endregion
51
+ export { Badge, badgeVariants };
@@ -0,0 +1,46 @@
1
+ import { ReactNode } from "react";
2
+ import { VariantProps } from "class-variance-authority";
3
+ //#region src/native/atom/button.d.ts
4
+ /**
5
+ * A button with the same variants and look as the web base/button (indigo primary action, raised surface + faint border, control corner radius).
6
+ * Only the height differs: it is larger than the web's (default 36) because it is pressed with a finger.
7
+ *
8
+ * Where `base/button` (`@expo/ui`) renders an OS-native button (iOS 26 Liquid Glass, etc.),
9
+ * this one is an RN `Pressable`, so it can be painted with tokens. **Use this one wherever it should look the same as the web.**
10
+ *
11
+ * The web's `hover:` does not exist in RN, so it is mapped to `pressed` while pressed.
12
+ *
13
+ * The web Button is `inline-flex`, so it shrinks to its content. An RN `Pressable` stretches across
14
+ * the parent's cross axis, so `self-start` gives it the same behavior. For a full-width CTA,
15
+ * pass `className="self-stretch"` from the consumer.
16
+ */
17
+ declare const buttonVariants: (props?: ({
18
+ variant?: "<3" | "default" | "destructive" | "ghost" | "link" | "outline" | "plate" | "secondary" | null | undefined;
19
+ size?: "default" | "icon" | "icon-xs" | "lg" | "sm" | "xl" | "xs" | null | undefined;
20
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
21
+ declare const buttonTextVariants: (props?: ({
22
+ variant?: "<3" | "default" | "destructive" | "ghost" | "link" | "outline" | "plate" | "secondary" | null | undefined;
23
+ size?: "default" | "icon" | "icon-xs" | "lg" | "sm" | "xl" | "xs" | null | undefined;
24
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
25
+ export type ButtonVariants = VariantProps<typeof buttonVariants>;
26
+ export type ButtonProps = ButtonVariants & {
27
+ children?: ReactNode;
28
+ onPress?: () => void;
29
+ disabled?: boolean;
30
+ /**
31
+ * Elements placed to the left and right of the label. The web takes a lucide component type, but native
32
+ * icon renderers vary (`@expo/vector-icons`, `expo-symbols`, etc.), so it takes already-rendered elements.
33
+ */
34
+ iconLeft?: ReactNode;
35
+ iconRight?: ReactNode;
36
+ /**
37
+ * Name for screen readers and E2E. **Always pass it when buttons with the same text appear in a list
38
+ * (a per-row "Delete", etc.).** Without it VoiceOver cannot tell which row a button belongs to, and E2E cannot target them individually.
39
+ */
40
+ accessibilityLabel?: string;
41
+ className?: string;
42
+ textClassName?: string;
43
+ };
44
+ export declare function Button({ children, onPress, disabled, variant, size, iconLeft, iconRight, accessibilityLabel, className, textClassName }: ButtonProps): import("react").JSX.Element;
45
+ //#endregion
46
+ export { buttonTextVariants, buttonVariants };
@@ -0,0 +1,109 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { Text as Text$1, TextClassContext } from "../base/text.js";
3
+ import { useState } from "react";
4
+ import { Pressable } from "react-native";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { cva } from "class-variance-authority";
7
+
8
+ //#region src/native/atom/button.tsx
9
+ /**
10
+ * A button with the same variants and look as the web base/button (indigo primary action, raised surface + faint border, control corner radius).
11
+ * Only the height differs: it is larger than the web's (default 36) because it is pressed with a finger.
12
+ *
13
+ * Where `base/button` (`@expo/ui`) renders an OS-native button (iOS 26 Liquid Glass, etc.),
14
+ * this one is an RN `Pressable`, so it can be painted with tokens. **Use this one wherever it should look the same as the web.**
15
+ *
16
+ * The web's `hover:` does not exist in RN, so it is mapped to `pressed` while pressed.
17
+ *
18
+ * The web Button is `inline-flex`, so it shrinks to its content. An RN `Pressable` stretches across
19
+ * the parent's cross axis, so `self-start` gives it the same behavior. For a full-width CTA,
20
+ * pass `className="self-stretch"` from the consumer.
21
+ */
22
+ const buttonVariants = cva("flex-row items-center justify-center gap-2 self-start rounded-control border border-transparent", {
23
+ variants: {
24
+ variant: {
25
+ default: "bg-action",
26
+ destructive: "bg-destructive-solid",
27
+ outline: "border-line-strong bg-raised",
28
+ secondary: "border-line-strong bg-raised",
29
+ ghost: "",
30
+ link: "",
31
+ plate: "border-black bg-white",
32
+ "<3": "bg-lt-three"
33
+ },
34
+ size: {
35
+ default: "h-9 px-4",
36
+ xs: "h-7 gap-1 px-2",
37
+ sm: "h-8 gap-1.5 px-3",
38
+ lg: "h-10 px-6",
39
+ xl: "h-12 px-6",
40
+ icon: "h-8 w-8",
41
+ "icon-xs": "h-7 w-7"
42
+ }
43
+ },
44
+ defaultVariants: {
45
+ variant: "default",
46
+ size: "default"
47
+ }
48
+ });
49
+ const buttonTextVariants = cva("font-medium", {
50
+ variants: {
51
+ variant: {
52
+ default: "text-action-foreground",
53
+ destructive: "text-destructive-solid-foreground",
54
+ outline: "text-foreground",
55
+ secondary: "text-secondary-foreground",
56
+ ghost: "text-foreground",
57
+ link: "text-action-ink underline",
58
+ plate: "font-normal text-black",
59
+ "<3": "text-lt-three-foreground"
60
+ },
61
+ size: {
62
+ default: "text-sm",
63
+ xs: "text-xs",
64
+ sm: "text-sm",
65
+ lg: "text-sm",
66
+ xl: "text-sm",
67
+ icon: "text-sm",
68
+ "icon-xs": "text-xs"
69
+ }
70
+ },
71
+ defaultVariants: {
72
+ variant: "default",
73
+ size: "default"
74
+ }
75
+ });
76
+ function Button({ children, onPress, disabled, variant, size, iconLeft, iconRight, accessibilityLabel, className, textClassName }) {
77
+ const textClass = cn(buttonTextVariants({
78
+ variant,
79
+ size
80
+ }), textClassName);
81
+ const [pressed, setPressed] = useState(false);
82
+ return /* @__PURE__ */ jsx(Pressable, {
83
+ onPress,
84
+ onPressIn: () => setPressed(true),
85
+ onPressOut: () => setPressed(false),
86
+ disabled,
87
+ accessibilityRole: "button",
88
+ "aria-disabled": disabled,
89
+ accessibilityLabel,
90
+ className: cn(buttonVariants({
91
+ variant,
92
+ size
93
+ }), pressed && "opacity-70", disabled && "opacity-50", className),
94
+ children: /* @__PURE__ */ jsxs(TextClassContext.Provider, {
95
+ value: textClass,
96
+ children: [
97
+ iconLeft,
98
+ typeof children === "string" || typeof children === "number" ? /* @__PURE__ */ jsx(Text$1, {
99
+ className: textClass,
100
+ children
101
+ }) : children,
102
+ iconRight
103
+ ]
104
+ })
105
+ });
106
+ }
107
+
108
+ //#endregion
109
+ export { Button, buttonTextVariants, buttonVariants };
@@ -0,0 +1,21 @@
1
+ import { NamedControlA11yProps } from "../lib/control.js";
2
+ import { ReactNode } from "react";
3
+ //#region src/native/atom/checkbox.d.ts
4
+ export type CheckboxProps = NamedControlA11yProps & {
5
+ checked: boolean;
6
+ onCheckedChange: (checked: boolean) => void;
7
+ /** Label shown to the right of the checkbox. It is part of the tap area. */
8
+ label?: ReactNode;
9
+ /** Name for screen readers. A string label is used as-is, so pass this when there is no label or it is not a string. */
10
+ accessibilityLabel?: string;
11
+ disabled?: boolean;
12
+ invalid?: boolean;
13
+ className?: string;
14
+ wrapperClassName?: string;
15
+ };
16
+ /**
17
+ * A 16px square with the control corner radius, identical to the web base/checkbox.
18
+ * Unchecked is a raised surface + a line-control border (3:1); checked is an indigo fill + a white check.
19
+ */
20
+ export declare function Checkbox({ checked, onCheckedChange, label, accessibilityLabel, disabled, invalid, className, wrapperClassName, accessibilityHint, id, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid }: CheckboxProps): import("react").JSX.Element;
21
+ //#endregion
@@ -0,0 +1,47 @@
1
+ import { useTokenColor } from "../lib/token-color.js";
2
+ import { cn } from "../lib/utils.js";
3
+ import { Text as Text$1 } from "../base/text.js";
4
+ import { activateOnSpace } from "../lib/keyboard.js";
5
+ import { Pressable, View } from "react-native";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import Feather from "@expo/vector-icons/Feather";
8
+
9
+ //#region src/native/atom/checkbox.tsx
10
+ /**
11
+ * A 16px square with the control corner radius, identical to the web base/checkbox.
12
+ * Unchecked is a raised surface + a line-control border (3:1); checked is an indigo fill + a white check.
13
+ */
14
+ function Checkbox({ checked, onCheckedChange, label, accessibilityLabel, disabled, invalid, className, wrapperClassName, accessibilityHint, id, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid }) {
15
+ const isInvalid = invalid ?? ariaInvalid;
16
+ const checkColor = useTokenColor("--action-foreground");
17
+ const box = /* @__PURE__ */ jsx(View, {
18
+ className: cn("h-4 w-4 shrink-0 items-center justify-center rounded-control border", checked ? "border-action bg-action" : "border-line-control bg-raised", isInvalid && "border-destructive", disabled && "opacity-50", className),
19
+ children: checked ? /* @__PURE__ */ jsx(Feather, {
20
+ name: "check",
21
+ size: 12,
22
+ color: checkColor
23
+ }) : null
24
+ });
25
+ return /* @__PURE__ */ jsxs(Pressable, {
26
+ accessibilityRole: "checkbox",
27
+ accessibilityLabel: accessibilityLabel ?? (typeof label === "string" ? label : void 0),
28
+ "aria-checked": checked,
29
+ "aria-disabled": disabled,
30
+ "aria-invalid": isInvalid,
31
+ "aria-describedby": ariaDescribedBy,
32
+ accessibilityHint,
33
+ id,
34
+ onPress: () => onCheckedChange(!checked),
35
+ onKeyDown: activateOnSpace(() => onCheckedChange(!checked), disabled),
36
+ disabled,
37
+ hitSlop: 12,
38
+ className: cn("flex-row items-center gap-1.5 self-start", wrapperClassName),
39
+ children: [box, label === void 0 ? null : typeof label === "string" || typeof label === "number" ? /* @__PURE__ */ jsx(Text$1, {
40
+ className: "text-sm font-medium leading-none",
41
+ children: label
42
+ }) : label]
43
+ });
44
+ }
45
+
46
+ //#endregion
47
+ export { Checkbox };
@@ -0,0 +1,12 @@
1
+ import { ColoredValueSharedProps } from "../../shared/analytics.js";
2
+ import { ReactNode } from "react";
3
+ //#region src/native/atom/colored-value.d.ts
4
+ export type ColoredValueProps<TValue> = ColoredValueSharedProps<TValue>;
5
+ /**
6
+ * A number whose color changes with its sign. Same API as the web atom/colored-value (`shared/analytics.ts`).
7
+ * The default colors are the tokens `state-success` / `state-error` rather than Tailwind's fixed palette (green-500 / red-500),
8
+ * and they keep 4.5:1 contrast in dark mode too.
9
+ * Being a number, it is drawn monospaced (tabular).
10
+ */
11
+ export declare function ColoredValue<TValue>({ value, format, isPositive, isNegative, positiveColor, negativeColor, className }: ColoredValueProps<TValue>): ReactNode;
12
+ //#endregion
@@ -0,0 +1,24 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { Text } from "../base/text.js";
3
+ import { tabularNums } from "../lib/typography.js";
4
+ import { jsx } from "react/jsx-runtime";
5
+
6
+ //#region src/native/atom/colored-value.tsx
7
+ /**
8
+ * A number whose color changes with its sign. Same API as the web atom/colored-value (`shared/analytics.ts`).
9
+ * The default colors are the tokens `state-success` / `state-error` rather than Tailwind's fixed palette (green-500 / red-500),
10
+ * and they keep 4.5:1 contrast in dark mode too.
11
+ * Being a number, it is drawn monospaced (tabular).
12
+ */
13
+ function ColoredValue({ value, format, isPositive, isNegative, positiveColor = "text-state-success", negativeColor = "text-state-error", className }) {
14
+ const formatted = format ? format(value) : String(value);
15
+ const toneClass = isPositive?.(value) ? positiveColor : isNegative?.(value) ? negativeColor : void 0;
16
+ return /* @__PURE__ */ jsx(Text, {
17
+ style: tabularNums,
18
+ className: cn("font-mono", toneClass, className),
19
+ children: formatted
20
+ });
21
+ }
22
+
23
+ //#endregion
24
+ export { ColoredValue };
@@ -0,0 +1,21 @@
1
+ //#region src/native/atom/image.d.ts
2
+ export type ImageWithLoaderProps = {
3
+ src: string;
4
+ /** Description for screen readers. Corresponds to the web `alt`. */
5
+ alt: string;
6
+ /** Opens a full-screen view on tap (default true). */
7
+ expandable?: boolean;
8
+ /** Text shown when loading fails. This is a shared package, so consumers own the wording. */
9
+ errorText?: string;
10
+ /** Screen reader name of the expand button. */
11
+ expandLabel?: string;
12
+ /** Screen reader name of the button that closes the expanded view. */
13
+ closeLabel?: string;
14
+ className?: string;
15
+ };
16
+ /**
17
+ * An image that shows a skeleton while loading and a placeholder on failure.
18
+ * Mirrors the web atom/image (ImageWithLoader).
19
+ */
20
+ export declare function ImageWithLoader({ src, alt, expandable, errorText, expandLabel, closeLabel, className }: ImageWithLoaderProps): import("react").JSX.Element;
21
+ //#endregion
@@ -0,0 +1,72 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { Text as Text$1 } from "../base/text.js";
3
+ import { Skeleton } from "./skeleton.js";
4
+ import { useState } from "react";
5
+ import { Modal, Pressable, View } from "react-native";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { Image } from "expo-image";
8
+
9
+ //#region src/native/atom/image.tsx
10
+ /**
11
+ * An image that shows a skeleton while loading and a placeholder on failure.
12
+ * Mirrors the web atom/image (ImageWithLoader).
13
+ */
14
+ function ImageWithLoader({ src, alt, expandable = true, errorText = "画像の読み込みに失敗しました", expandLabel = "画像を拡大する", closeLabel = "閉じる", className }) {
15
+ const [status, setStatus] = useState("loading");
16
+ const [expanded, setExpanded] = useState(false);
17
+ if (status === "error") return /* @__PURE__ */ jsx(View, {
18
+ className: cn("items-center justify-center bg-muted p-5", className),
19
+ children: /* @__PURE__ */ jsx(Text$1, {
20
+ className: "text-muted-foreground text-sm",
21
+ children: errorText
22
+ })
23
+ });
24
+ const image = /* @__PURE__ */ jsx(Image, {
25
+ source: { uri: src },
26
+ accessibilityLabel: alt,
27
+ contentFit: "cover",
28
+ style: {
29
+ width: "100%",
30
+ height: "100%"
31
+ },
32
+ onLoad: () => setStatus("loaded"),
33
+ onError: () => setStatus("error")
34
+ });
35
+ return /* @__PURE__ */ jsxs(View, {
36
+ className: cn("overflow-hidden", className),
37
+ children: [
38
+ status === "loading" ? /* @__PURE__ */ jsx(Skeleton, { className: "absolute inset-0" }) : null,
39
+ expandable ? /* @__PURE__ */ jsx(Pressable, {
40
+ accessibilityRole: "button",
41
+ accessibilityLabel: alt === "" ? expandLabel : `${alt}(${expandLabel})`,
42
+ className: "h-full w-full",
43
+ onPress: () => setExpanded(true),
44
+ children: image
45
+ }) : image,
46
+ /* @__PURE__ */ jsx(Modal, {
47
+ visible: expanded,
48
+ transparent: true,
49
+ animationType: "fade",
50
+ onRequestClose: () => setExpanded(false),
51
+ children: /* @__PURE__ */ jsx(Pressable, {
52
+ accessibilityRole: "button",
53
+ accessibilityLabel: closeLabel,
54
+ className: "flex-1 items-center justify-center bg-scrim p-4",
55
+ onPress: () => setExpanded(false),
56
+ children: /* @__PURE__ */ jsx(Image, {
57
+ source: { uri: src },
58
+ accessibilityLabel: alt,
59
+ contentFit: "contain",
60
+ style: {
61
+ flex: 1,
62
+ width: "100%"
63
+ }
64
+ })
65
+ })
66
+ })
67
+ ]
68
+ });
69
+ }
70
+
71
+ //#endregion
72
+ export { ImageWithLoader };
@@ -0,0 +1,18 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/native/atom/label.d.ts
3
+ export type LabelProps = {
4
+ children: ReactNode;
5
+ /** Adds the required mark (`*`). */
6
+ required?: boolean;
7
+ /** Supplementary text placed to the right of the label. */
8
+ helpText?: ReactNode;
9
+ className?: string;
10
+ /** The `id` of the text part. Point to it from the input's `aria-labelledby` (the required `*` and the supplementary text are not part of the name). */
11
+ id?: string;
12
+ };
13
+ /**
14
+ * A label that looks the same as the web base/label.
15
+ * RN has no equivalent of the web's `htmlFor`, so tapping the label does not move focus to the input.
16
+ */
17
+ export declare function Label({ children, required, helpText, className, id }: LabelProps): import("react").JSX.Element;
18
+ //#endregion
@@ -0,0 +1,33 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { Text as Text$1 } from "../base/text.js";
3
+ import { View } from "react-native";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+
6
+ //#region src/native/atom/label.tsx
7
+ /**
8
+ * A label that looks the same as the web base/label.
9
+ * RN has no equivalent of the web's `htmlFor`, so tapping the label does not move focus to the input.
10
+ */
11
+ function Label({ children, required, helpText, className, id }) {
12
+ return /* @__PURE__ */ jsxs(View, {
13
+ className: "flex-row items-center gap-2",
14
+ children: [
15
+ /* @__PURE__ */ jsx(Text$1, {
16
+ id,
17
+ className: cn("text-sm font-medium leading-none", className),
18
+ children
19
+ }),
20
+ required ? /* @__PURE__ */ jsx(Text$1, {
21
+ className: "text-destructive text-sm",
22
+ children: "*"
23
+ }) : null,
24
+ helpText ? /* @__PURE__ */ jsx(Text$1, {
25
+ className: "text-muted-foreground text-xs font-normal",
26
+ children: helpText
27
+ }) : null
28
+ ]
29
+ });
30
+ }
31
+
32
+ //#endregion
33
+ export { Label };