@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,10 +1,12 @@
1
- import { Skeleton } from './chunk-RIBDXGUG.js';
2
- import { Button } from './chunk-3ARE4TES.js';
3
- import { Icon } from './chunk-TKVFVF5D.js';
1
+ import { Skeleton } from './chunk-PNF3NKB5.js';
2
+ import { Button } from './chunk-E2E3I5W2.js';
3
+ import { useLabels, useLoamLocale } from './chunk-APCWFOZW.js';
4
+ import { Icon } from './chunk-UXGIW7OK.js';
5
+ import { springConfig } from './chunk-J64KGCGX.js';
4
6
  import * as React2 from 'react';
5
- import { PanResponder, View, Text, Pressable, ScrollView } from 'react-native';
7
+ import { Animated, PanResponder, View, Text, Pressable, ScrollView } from 'react-native';
6
8
  import Svg, { Defs, LinearGradient, Stop, Pattern, Rect, ClipPath, G, Text as Text$1, Circle, Path } from 'react-native-svg';
7
- import { createValuePalette, FULL_WINDOW, normalizeSpec, resolveHeight, isWholePlot, renderChart, tableModel, describeChart, readoutRows, pick, clampWindow, zoomAt, isZoomed, panBy, toCsv, NARROW_WIDTH, TIGHT_WIDTH, sceneToSvg } from '@btndprojects/loam-charts';
9
+ import { DEFAULT_CHART_LABELS, createValuePalette, FULL_WINDOW, normalizeSpec, resolveHeight, isWholePlot, renderChart, tableModel, describeChart, readoutRows, pick, clampWindow, zoomAt, isZoomed, panBy, toCsv, NARROW_WIDTH, TIGHT_WIDTH, sceneToSvg } from '@btndprojects/loam-charts';
8
10
  import { createStyleSheet, useLoamTheme, useStyles } from '@btndprojects/loam-theme-native';
9
11
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
10
12
 
@@ -152,6 +154,28 @@ function SceneDefsNodes({ defs, clipId }) {
152
154
  /* @__PURE__ */ jsx(ClipPath, { id: clipId, children: /* @__PURE__ */ jsx(Rect, { x: defs.clip.x, y: defs.clip.y, width: defs.clip.w, height: defs.clip.h }) })
153
155
  ] });
154
156
  }
157
+ var DEFAULT_CHART_UI_LABELS = {
158
+ ...DEFAULT_CHART_LABELS,
159
+ hideTable: "Hide the data table",
160
+ showTable: "Show the data table",
161
+ exportCsv: "Export the visible window as CSV",
162
+ shareImage: "Share the chart as an image",
163
+ readoutPlaceholder: "Drag across the chart to read values.",
164
+ clearReading: "Clear the reading",
165
+ legendHint: "tap to filter \xB7 hold to solo",
166
+ loading: "Loading chart",
167
+ emptyTitle: "No data in this range",
168
+ emptyText: "The series exist \u2014 the window is empty. Widen the range or clear a filter.",
169
+ clearFilter: "Clear the filter",
170
+ errorTitle: "That data did not load",
171
+ errorText: "Nothing was drawn, because a chart of nothing looks exactly like a chart of zero.",
172
+ tryAgain: "Try again",
173
+ resetZoomA11y: "Reset the zoom",
174
+ resetZoom: "Reset zoom",
175
+ source: (source) => "Source: " + source,
176
+ dataCaption: "Chart data",
177
+ tableRows: (caption, count) => caption + " \u2014 " + count + " rows"
178
+ };
155
179
  var UID = 0;
156
180
  function svgDocument(frame, uid, width, height, fonts) {
157
181
  const body = sceneToSvg(frame.scene, frame.defs, uid);
@@ -169,9 +193,12 @@ function Chart({
169
193
  onExportImage,
170
194
  onVisibilityChange,
171
195
  onZoomChange,
196
+ copy,
172
197
  ...specInput
173
198
  }) {
174
- const theme = useLoamTheme();
199
+ const labels = useLabels("chart", DEFAULT_CHART_UI_LABELS, copy);
200
+ const providerLocale = useLoamLocale();
201
+ const theme = useLoamTheme("chart");
175
202
  const { styles } = useStyles(stylesheet);
176
203
  const uid = React2.useMemo(() => "lc" + ++UID, []);
177
204
  const palette = React2.useMemo(() => nativeChartPalette(theme), [theme]);
@@ -181,8 +208,36 @@ function Chart({
181
208
  const [pinned, setPinned] = React2.useState(null);
182
209
  const [tableOpen, setTableOpen] = React2.useState(defaultTableOpen);
183
210
  const [zoom, setZoomState] = React2.useState(FULL_WINDOW);
184
- const spec = React2.useMemo(() => normalizeSpec(specInput), [specInput]);
211
+ const spec = React2.useMemo(
212
+ () => normalizeSpec({
213
+ ...specInput,
214
+ locale: specInput.locale ?? providerLocale,
215
+ copy: { ...labels, ...specInput.copy }
216
+ }),
217
+ [specInput, labels, providerLocale]
218
+ );
185
219
  const measured = width || 360;
220
+ const entry = React2.useRef(
221
+ new Animated.Value(spec.animate && !theme.reduceMotion ? 0 : 1)
222
+ ).current;
223
+ const entered = React2.useRef(false);
224
+ React2.useEffect(() => {
225
+ if (!width || entered.current) return;
226
+ entered.current = true;
227
+ if (!spec.animate || theme.reduceMotion) {
228
+ entry.setValue(1);
229
+ return;
230
+ }
231
+ Animated.spring(entry, {
232
+ ...springConfig(theme, "ds"),
233
+ toValue: 1,
234
+ useNativeDriver: true
235
+ }).start();
236
+ }, [width, spec.animate, theme, entry]);
237
+ const entryStyle = {
238
+ opacity: entry.interpolate({ inputRange: [0, 1], outputRange: [0, 1], extrapolate: "clamp" }),
239
+ transform: [{ translateY: entry.interpolate({ inputRange: [0, 1], outputRange: [8, 0] }) }]
240
+ };
186
241
  const narrow = measured < NARROW_WIDTH;
187
242
  const tight = measured < TIGHT_WIDTH;
188
243
  const height = resolveHeight(spec, measured, narrow);
@@ -222,7 +277,10 @@ function Chart({
222
277
  const x = (lx - originRef.current.x) * k;
223
278
  const y = (ly - originRef.current.y) * k;
224
279
  const mode = s.tooltip.trigger === "item" ? "nearest" : "index";
225
- const hit = pick(f.items, x, y, isWholePlot(s.type) ? "nearest" : mode, { radius: 56, horizontal: f.horizontal });
280
+ const hit = pick(f.items, x, y, isWholePlot(s.type) ? "nearest" : mode, {
281
+ radius: 56,
282
+ horizontal: f.horizontal
283
+ });
226
284
  if (hit) {
227
285
  setPinned({ si: hit.si, di: hit.di, kind: hit.linkKind });
228
286
  s.onSelect?.(hit, s.series[hit.si]);
@@ -242,15 +300,18 @@ function Chart({
242
300
  const resetZoom = React2.useCallback(() => setZoom(FULL_WINDOW), [setZoom]);
243
301
  const pinchRef = React2.useRef(null);
244
302
  const lastTapRef = React2.useRef(0);
245
- const pinchGeometry = React2.useCallback((touches) => {
246
- const [a, b] = touches;
247
- if (!a || !b) return null;
248
- const dist = Math.hypot(a.pageX - b.pageX, a.pageY - b.pageY);
249
- const f = frameRef.current;
250
- const plot = f.plot;
251
- const midX = (a.pageX + b.pageX) / 2 - originRef.current.x - plot.x;
252
- return { dist, anchor: plot.w ? Math.min(1, Math.max(0, midX / plot.w)) : 0.5 };
253
- }, []);
303
+ const pinchGeometry = React2.useCallback(
304
+ (touches) => {
305
+ const [a, b] = touches;
306
+ if (!a || !b) return null;
307
+ const dist = Math.hypot(a.pageX - b.pageX, a.pageY - b.pageY);
308
+ const f = frameRef.current;
309
+ const plot = f.plot;
310
+ const midX = (a.pageX + b.pageX) / 2 - originRef.current.x - plot.x;
311
+ return { dist, anchor: plot.w ? Math.min(1, Math.max(0, midX / plot.w)) : 0.5 };
312
+ },
313
+ []
314
+ );
254
315
  const responder = React2.useMemo(
255
316
  () => PanResponder.create({
256
317
  onStartShouldSetPanResponder: () => true,
@@ -298,13 +359,21 @@ function Chart({
298
359
  [scrub, zoomEnabled, resetZoom, setZoom, pinchGeometry]
299
360
  );
300
361
  const legendEntries = React2.useMemo(() => {
301
- const itemLegend = ["pie", "donut", "polarArea", "funnel", "pyramid", "radialBar", "waffle"].includes(spec.type);
362
+ const itemLegend = [
363
+ "pie",
364
+ "donut",
365
+ "polarArea",
366
+ "funnel",
367
+ "pyramid",
368
+ "radialBar",
369
+ "waffle"
370
+ ].includes(spec.type);
302
371
  if (wholePlot && !itemLegend) return [];
303
372
  if (wholePlot) {
304
373
  const raw = spec.series[0]?.data || spec.data;
305
374
  return (Array.isArray(raw) ? raw : []).map((d, i) => ({
306
375
  id: "i" + i,
307
- label: (d && typeof d === "object" ? d.label : null) || (spec.xAxis.data || [])[i] || "Item " + (i + 1),
376
+ label: (d && typeof d === "object" ? d.label : null) || (spec.xAxis.data || [])[i] || spec.copy.itemN(i + 1),
308
377
  color: palette.series(i),
309
378
  edge: palette.edge(i),
310
379
  off: false,
@@ -419,7 +488,7 @@ function Chart({
419
488
  ToolButton,
420
489
  {
421
490
  icon: "grid",
422
- label: tableOpen ? "Hide the data table" : "Show the data table",
491
+ label: tableOpen ? labels.hideTable : labels.showTable,
423
492
  active: tableOpen,
424
493
  onPress: () => setTableOpen((v) => !v)
425
494
  }
@@ -428,15 +497,18 @@ function Chart({
428
497
  ToolButton,
429
498
  {
430
499
  icon: "download",
431
- label: "Export the visible window as CSV",
432
- onPress: () => onExportCsv(toCsv(table), (spec.title || "chart").replace(/[^\w.-]+/g, "-") + ".csv")
500
+ label: labels.exportCsv,
501
+ onPress: () => onExportCsv(
502
+ toCsv(table),
503
+ (spec.title || "chart").replace(/[^\w.-]+/g, "-") + ".csv"
504
+ )
433
505
  }
434
506
  ) : null,
435
507
  onExportImage ? /* @__PURE__ */ jsx(
436
508
  ToolButton,
437
509
  {
438
510
  icon: "image",
439
- label: "Share the chart as an image",
511
+ label: labels.shareImage,
440
512
  onPress: () => onExportImage(
441
513
  svgDocument(frame, uid, measured, height, {
442
514
  sans: theme.font.sans,
@@ -448,11 +520,19 @@ function Chart({
448
520
  ) : null
449
521
  ] })
450
522
  ] }),
451
- showReadout && state === "ready" ? /* @__PURE__ */ jsx(View, { style: styles.readout, accessibilityLiveRegion: "polite", children: rows.length === 0 ? /* @__PURE__ */ jsx(Text, { style: styles.readoutHint, children: "Drag across the chart to read values." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
523
+ showReadout && state === "ready" ? /* @__PURE__ */ jsx(View, { style: styles.readout, accessibilityLiveRegion: "polite", children: rows.length === 0 ? /* @__PURE__ */ jsx(Text, { style: styles.readoutHint, children: labels.readoutPlaceholder }) : /* @__PURE__ */ jsxs(Fragment, { children: [
452
524
  /* @__PURE__ */ jsxs(View, { style: styles.readoutBody, children: [
453
525
  /* @__PURE__ */ jsx(Text, { style: styles.readoutLabel, children: frame.axisLabels[pinned?.di ?? 0] }),
454
526
  /* @__PURE__ */ jsx(View, { style: styles.readoutRows, children: rows.map((r, i) => /* @__PURE__ */ jsxs(View, { style: styles.readoutRow, children: [
455
- /* @__PURE__ */ jsx(View, { style: [styles.swatch, { backgroundColor: r.color, borderColor: r.edge ?? r.color }] }),
527
+ /* @__PURE__ */ jsx(
528
+ View,
529
+ {
530
+ style: [
531
+ styles.swatch,
532
+ { backgroundColor: r.color, borderColor: r.edge ?? r.color }
533
+ ]
534
+ }
535
+ ),
456
536
  /* @__PURE__ */ jsxs(Text, { style: styles.readoutName, children: [
457
537
  r.label,
458
538
  ":"
@@ -464,65 +544,97 @@ function Chart({
464
544
  Pressable,
465
545
  {
466
546
  accessibilityRole: "button",
467
- accessibilityLabel: "Clear the reading",
547
+ accessibilityLabel: labels.clearReading,
468
548
  style: ({ pressed }) => [styles.readoutClear, pressed && styles.pressed],
469
549
  onPress: () => setPinned(null),
470
550
  children: /* @__PURE__ */ jsx(Icon, { name: "x", size: 15, color: theme.color.text3 })
471
551
  }
472
552
  )
473
553
  ] }) }) : null,
474
- legendEntries.length > 1 ? /* @__PURE__ */ jsxs(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, contentContainerStyle: styles.legend, children: [
475
- legendEntries.map((en) => /* @__PURE__ */ jsxs(
476
- Pressable,
477
- {
478
- accessibilityRole: "button",
479
- accessibilityState: { selected: !en.off },
480
- accessibilityLabel: en.label,
481
- hitSlop: { top: theme.space[6], bottom: theme.space[6], left: theme.space[4], right: theme.space[4] },
482
- style: ({ pressed }) => [styles.chip, en.off && styles.chipOff, pressed && styles.pressed],
483
- onPress: () => toggle(en.id, en.index),
484
- onLongPress: () => setSolo((s) => s === en.index ? null : en.index),
485
- children: [
486
- /* @__PURE__ */ jsx(
487
- View,
488
- {
489
- style: [
490
- styles.swatch,
491
- // Outlined in the series edge: the pastel fill alone does
492
- // not clear 3:1 on the card.
493
- { backgroundColor: en.color, borderColor: en.edge },
494
- // The web twin greys the chip with `grayscale(1)`; RN has no
495
- // filter, so the muting is the system's own disabled opacity
496
- // rather than a hand-picked number. Only the *swatch* dims —
497
- // see the `chipOff` note for why the label does not.
498
- en.off && { opacity: theme.state.disabledOpacity }
499
- ]
500
- }
501
- ),
502
- /* @__PURE__ */ jsx(Text, { style: [styles.chipText, en.off && styles.chipTextOff], children: en.label })
503
- ]
504
- },
505
- en.id
506
- )),
507
- /* @__PURE__ */ jsx(Text, { style: styles.legendHint, children: "tap to filter \xB7 hold to solo" })
508
- ] }) : null,
554
+ legendEntries.length > 1 ? /* @__PURE__ */ jsxs(
555
+ ScrollView,
556
+ {
557
+ horizontal: true,
558
+ showsHorizontalScrollIndicator: false,
559
+ contentContainerStyle: styles.legend,
560
+ children: [
561
+ legendEntries.map((en) => /* @__PURE__ */ jsxs(
562
+ Pressable,
563
+ {
564
+ accessibilityRole: "button",
565
+ accessibilityState: { selected: !en.off },
566
+ accessibilityLabel: en.label,
567
+ hitSlop: {
568
+ top: theme.space[6],
569
+ bottom: theme.space[6],
570
+ left: theme.space[4],
571
+ right: theme.space[4]
572
+ },
573
+ style: ({ pressed }) => [
574
+ styles.chip,
575
+ en.off && styles.chipOff,
576
+ pressed && styles.pressed
577
+ ],
578
+ onPress: () => toggle(en.id, en.index),
579
+ onLongPress: () => setSolo((s) => s === en.index ? null : en.index),
580
+ children: [
581
+ /* @__PURE__ */ jsx(
582
+ View,
583
+ {
584
+ style: [
585
+ styles.swatch,
586
+ // Outlined in the series edge: the pastel fill alone does
587
+ // not clear 3:1 on the card.
588
+ { backgroundColor: en.color, borderColor: en.edge },
589
+ // The web twin greys the chip with `grayscale(1)`; RN has no
590
+ // filter, so the muting is the system's own disabled opacity
591
+ // rather than a hand-picked number. Only the *swatch* dims —
592
+ // see the `chipOff` note for why the label does not.
593
+ en.off && { opacity: theme.state.disabledOpacity }
594
+ ]
595
+ }
596
+ ),
597
+ /* @__PURE__ */ jsx(Text, { style: [styles.chipText, en.off && styles.chipTextOff], children: en.label })
598
+ ]
599
+ },
600
+ en.id
601
+ )),
602
+ /* @__PURE__ */ jsx(Text, { style: styles.legendHint, children: labels.legendHint })
603
+ ]
604
+ }
605
+ ) : null,
509
606
  /* @__PURE__ */ jsx(View, { style: styles.plotWrap, children: /* @__PURE__ */ jsxs(View, { onLayout: onPlotLayout, style: styles.plot, children: [
510
607
  state === "loading" ? /* @__PURE__ */ jsx(
511
608
  View,
512
609
  {
513
610
  accessible: true,
514
611
  accessibilityRole: "progressbar",
515
- accessibilityLabel: "Loading chart",
612
+ accessibilityLabel: labels.loading,
516
613
  style: [styles.skeleton, { height }],
517
- children: Array.from({ length: 10 }, (_, i) => /* @__PURE__ */ jsx(Skeleton, { style: { flex: 1, height: 28 + i * 37 % 62 + "%" }, radius: "sm" }, i))
614
+ children: Array.from({ length: 10 }, (_, i) => /* @__PURE__ */ jsx(
615
+ Skeleton,
616
+ {
617
+ style: { flex: 1, height: 28 + i * 37 % 62 + "%" },
618
+ radius: "sm",
619
+ decorative: true
620
+ },
621
+ i
622
+ ))
518
623
  }
519
624
  ) : null,
520
625
  state === "empty" || state === "error" ? /* @__PURE__ */ jsxs(View, { style: [styles.message, { minHeight: Math.max(180, height * 0.7) }], children: [
521
- /* @__PURE__ */ jsx(View, { style: styles.messageIcon, children: /* @__PURE__ */ jsx(Icon, { name: state === "error" ? "alert-triangle" : "chart-bar", size: 22, color: theme.color.text3 }) }),
522
- /* @__PURE__ */ jsx(Text, { style: styles.messageTitle, children: state === "error" ? frame.problem?.title || spec.errorTitle || "That data did not load" : spec.emptyTitle || "No data in this range" }),
523
- /* @__PURE__ */ jsx(Text, { style: styles.messageText, children: state === "error" ? frame.problem?.text || spec.errorText || "Nothing was drawn, because a chart of nothing looks exactly like a chart of zero." : spec.emptyText || "The series exist \u2014 the window is empty. Widen the range or clear a filter." }),
524
- state === "error" && spec.onRetry ? /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onPress: spec.onRetry, children: "Try again" }) : null,
525
- state === "empty" && spec.onReset ? /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onPress: spec.onReset, children: "Clear the filter" }) : null
626
+ /* @__PURE__ */ jsx(View, { style: styles.messageIcon, children: /* @__PURE__ */ jsx(
627
+ Icon,
628
+ {
629
+ name: state === "error" ? "alert-triangle" : "chart-bar",
630
+ size: 22,
631
+ color: theme.color.text3
632
+ }
633
+ ) }),
634
+ /* @__PURE__ */ jsx(Text, { style: styles.messageTitle, children: state === "error" ? frame.problem?.title || spec.errorTitle || labels.errorTitle : spec.emptyTitle || labels.emptyTitle }),
635
+ /* @__PURE__ */ jsx(Text, { style: styles.messageText, children: state === "error" ? frame.problem?.text || spec.errorText || labels.errorText : spec.emptyText || labels.emptyText }),
636
+ state === "error" && spec.onRetry ? /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onPress: spec.onRetry, children: labels.tryAgain }) : null,
637
+ state === "empty" && spec.onReset ? /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onPress: spec.onReset, children: labels.clearFilter }) : null
526
638
  ] }) : null,
527
639
  state === "ready" ? /* @__PURE__ */ jsx(
528
640
  View,
@@ -536,16 +648,25 @@ function Chart({
536
648
  onLayout: (e) => {
537
649
  originRef.current = { x: 0, y: 0 };
538
650
  },
539
- children: /* @__PURE__ */ jsxs(Svg, { width: "100%", height, viewBox: `0 0 ${measured} ${height}`, children: [
651
+ children: /* @__PURE__ */ jsx(Animated.View, { style: entryStyle, children: /* @__PURE__ */ jsxs(Svg, { width: "100%", height, viewBox: `0 0 ${measured} ${height}`, children: [
540
652
  /* @__PURE__ */ jsx(SceneDefsNodes, { defs: frame.defs, clipId: uid + "-clip" }),
541
653
  /* @__PURE__ */ jsx(SceneNodes, { scene: frame.scene, theme, clipId: uid + "-clip" })
542
- ] })
654
+ ] }) })
543
655
  }
544
656
  ) : null,
545
- zoomEnabled && isZoomed(zoom) ? /* @__PURE__ */ jsx(View, { style: styles.zoomPill, children: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onPress: resetZoom, accessibilityLabel: "Reset the zoom", children: "Reset zoom" }) }) : null
657
+ zoomEnabled && isZoomed(zoom) ? /* @__PURE__ */ jsx(View, { style: styles.zoomPill, children: /* @__PURE__ */ jsx(
658
+ Button,
659
+ {
660
+ variant: "outline",
661
+ size: "sm",
662
+ onPress: resetZoom,
663
+ accessibilityLabel: labels.resetZoomA11y,
664
+ children: labels.resetZoom
665
+ }
666
+ ) }) : null
546
667
  ] }) }),
547
- (spec.footnote || spec.source) && /* @__PURE__ */ jsx(View, { style: styles.caption, children: /* @__PURE__ */ jsx(Text, { style: styles.captionText, children: [spec.footnote, spec.source && "Source: " + spec.source].filter(Boolean).join(" \xB7 ") }) }),
548
- tableOpen ? /* @__PURE__ */ jsx(ChartDataTable, { model: table, title: spec.title }) : null
668
+ (spec.footnote || spec.source) && /* @__PURE__ */ jsx(View, { style: styles.caption, children: /* @__PURE__ */ jsx(Text, { style: styles.captionText, children: [spec.footnote, spec.source && labels.source(spec.source)].filter(Boolean).join(" \xB7 ") }) }),
669
+ tableOpen ? /* @__PURE__ */ jsx(ChartDataTable, { model: table, title: spec.title, labels }) : null
549
670
  ]
550
671
  }
551
672
  );
@@ -556,7 +677,7 @@ function ToolButton({
556
677
  active,
557
678
  onPress
558
679
  }) {
559
- const theme = useLoamTheme();
680
+ const theme = useLoamTheme("chart");
560
681
  const { styles } = useStyles(stylesheet);
561
682
  return /* @__PURE__ */ jsx(
562
683
  Pressable,
@@ -564,16 +685,25 @@ function ToolButton({
564
685
  accessibilityRole: "button",
565
686
  accessibilityLabel: label,
566
687
  accessibilityState: { selected: !!active },
567
- style: ({ pressed }) => [styles.toolButton, active && styles.toolButtonActive, pressed && styles.pressed],
688
+ style: ({ pressed }) => [
689
+ styles.toolButton,
690
+ active && styles.toolButtonActive,
691
+ pressed && styles.pressed
692
+ ],
568
693
  onPress,
569
694
  children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 17, color: active ? theme.color.accentStrong : theme.color.text2 })
570
695
  }
571
696
  );
572
697
  }
573
- function ChartDataTable({ model, title }) {
698
+ function ChartDataTable({
699
+ model,
700
+ title,
701
+ labels: labelsProp
702
+ }) {
703
+ const labels = useLabels("chart", DEFAULT_CHART_UI_LABELS, labelsProp);
574
704
  const { styles } = useStyles(stylesheet);
575
705
  return /* @__PURE__ */ jsxs(View, { style: styles.tableWrap, children: [
576
- /* @__PURE__ */ jsx(Text, { style: styles.tableCaption, children: (title || "Chart data") + " \u2014 " + model.rows.length + " rows" }),
706
+ /* @__PURE__ */ jsx(Text, { style: styles.tableCaption, children: labels.tableRows(title || labels.dataCaption, model.rows.length) }),
577
707
  /* @__PURE__ */ jsx(ScrollView, { horizontal: true, focusable: true, showsHorizontalScrollIndicator: true, children: /* @__PURE__ */ jsx(ScrollView, { style: styles.tableScroll, focusable: true, nestedScrollEnabled: true, children: /* @__PURE__ */ jsxs(View, { accessibilityRole: "none", children: [
578
708
  /* @__PURE__ */ jsx(View, { style: [styles.tr, styles.thead], children: model.head.map((h, i) => /* @__PURE__ */ jsx(Text, { style: [styles.th, i === 0 && styles.thFirst], children: h }, i)) }),
579
709
  model.rows.map((r, i) => /* @__PURE__ */ jsx(View, { style: [styles.tr, i % 2 ? styles.trAlt : null], children: r.map((c, j) => /* @__PURE__ */ jsx(Text, { style: [styles.td, j === 0 && styles.tdFirst], children: c }, j)) }, i))
@@ -605,8 +735,18 @@ var stylesheet = createStyleSheet((theme) => ({
605
735
  paddingBottom: theme.space.s3
606
736
  },
607
737
  headerText: { flex: 1, minWidth: 0, gap: theme.space.s1 },
608
- title: { fontFamily: theme.font.sans, fontSize: theme.fontSize[15], fontWeight: theme.fontWeight.extrabold, color: theme.color.text },
609
- subtitle: { fontFamily: theme.font.sans, fontSize: theme.fontSize[13], color: theme.color.text3, lineHeight: theme.space[18] },
738
+ title: {
739
+ fontFamily: theme.font.sans,
740
+ fontSize: theme.fontSize[15],
741
+ fontWeight: theme.fontWeight.extrabold,
742
+ color: theme.color.text
743
+ },
744
+ subtitle: {
745
+ fontFamily: theme.font.sans,
746
+ fontSize: theme.fontSize[13],
747
+ color: theme.color.text3,
748
+ lineHeight: theme.space[18]
749
+ },
610
750
  toolbar: { flexDirection: "row", gap: theme.space.s2 },
611
751
  toolButton: {
612
752
  width: theme.tapMin,
@@ -644,7 +784,11 @@ var stylesheet = createStyleSheet((theme) => ({
644
784
  backgroundColor: theme.color.surface2
645
785
  },
646
786
  readoutBody: { flex: 1, minWidth: 0, gap: theme.space.s1 },
647
- readoutHint: { fontFamily: theme.font.sans, fontSize: theme.fontSize[13], color: theme.color.text3 },
787
+ readoutHint: {
788
+ fontFamily: theme.font.sans,
789
+ fontSize: theme.fontSize[13],
790
+ color: theme.color.text3
791
+ },
648
792
  readoutLabel: {
649
793
  fontFamily: theme.font.mono,
650
794
  fontSize: theme.fontSize[11],
@@ -658,8 +802,17 @@ var stylesheet = createStyleSheet((theme) => ({
658
802
  rowGap: theme.space.s1
659
803
  },
660
804
  readoutRow: { flexDirection: "row", alignItems: "center", gap: theme.space[6] },
661
- readoutName: { fontFamily: theme.font.sans, fontSize: theme.fontSize[13], color: theme.color.text2 },
662
- readoutValue: { fontFamily: theme.font.sans, fontSize: theme.fontSize[13], fontWeight: theme.fontWeight.bold, color: theme.color.text },
805
+ readoutName: {
806
+ fontFamily: theme.font.sans,
807
+ fontSize: theme.fontSize[13],
808
+ color: theme.color.text2
809
+ },
810
+ readoutValue: {
811
+ fontFamily: theme.font.sans,
812
+ fontSize: theme.fontSize[13],
813
+ fontWeight: theme.fontWeight.bold,
814
+ color: theme.color.text
815
+ },
663
816
  readoutClear: {
664
817
  width: theme.space[38],
665
818
  height: theme.space[38],
@@ -670,7 +823,13 @@ var stylesheet = createStyleSheet((theme) => ({
670
823
  borderColor: theme.color.borderStrong,
671
824
  backgroundColor: theme.color.surface
672
825
  },
673
- legend: { flexDirection: "row", alignItems: "center", gap: theme.space.s2, paddingHorizontal: theme.space.s4, paddingBottom: theme.space.s3 },
826
+ legend: {
827
+ flexDirection: "row",
828
+ alignItems: "center",
829
+ gap: theme.space.s2,
830
+ paddingHorizontal: theme.space.s4,
831
+ paddingBottom: theme.space.s3
832
+ },
674
833
  chip: {
675
834
  flexDirection: "row",
676
835
  alignItems: "center",
@@ -687,17 +846,38 @@ var stylesheet = createStyleSheet((theme) => ({
687
846
  // — and dimming on top of that dims a *measured* ink: `text3` clears AA against the
688
847
  // surface with no headroom, so 60% puts an interactive control under it.
689
848
  chipOff: { borderColor: theme.color.border, backgroundColor: "transparent" },
690
- chipText: { fontFamily: theme.font.sans, fontSize: theme.fontSize[13], fontWeight: theme.fontWeight.semibold, color: theme.color.text2 },
849
+ chipText: {
850
+ fontFamily: theme.font.sans,
851
+ fontSize: theme.fontSize[13],
852
+ fontWeight: theme.fontWeight.semibold,
853
+ color: theme.color.text2
854
+ },
691
855
  chipTextOff: { color: theme.color.text3 },
692
- legendHint: { fontFamily: theme.font.mono, fontSize: theme.fontSize[11], color: theme.color.text3, paddingLeft: theme.space.s1 },
693
- swatch: { width: theme.space[9], height: theme.space[9], borderRadius: theme.radius[3], borderWidth: 1 },
856
+ legendHint: {
857
+ fontFamily: theme.font.mono,
858
+ fontSize: theme.fontSize[11],
859
+ color: theme.color.text3,
860
+ paddingLeft: theme.space.s1
861
+ },
862
+ swatch: {
863
+ width: theme.space[9],
864
+ height: theme.space[9],
865
+ borderRadius: theme.radius[3],
866
+ borderWidth: 1
867
+ },
694
868
  // The inset lives on a wrapper so the plot's own `onLayout` width is the
695
869
  // width the scene is drawn at — padding on the measured view would put the
696
870
  // viewBox and the drawn box out of step.
697
871
  plotWrap: { paddingHorizontal: theme.space.s4, paddingBottom: theme.space.s3 },
698
872
  plot: { position: "relative", minWidth: 0 },
699
873
  skeleton: { flexDirection: "row", alignItems: "flex-end", gap: theme.space[8] },
700
- message: { alignItems: "center", justifyContent: "center", gap: theme.space.s2, paddingHorizontal: theme.space.s5, paddingVertical: theme.space.s6 },
874
+ message: {
875
+ alignItems: "center",
876
+ justifyContent: "center",
877
+ gap: theme.space.s2,
878
+ paddingHorizontal: theme.space.s5,
879
+ paddingVertical: theme.space.s6
880
+ },
701
881
  messageIcon: {
702
882
  width: theme.tapMin,
703
883
  height: theme.tapMin,
@@ -706,8 +886,20 @@ var stylesheet = createStyleSheet((theme) => ({
706
886
  borderRadius: theme.radius.md,
707
887
  backgroundColor: theme.color.surface2
708
888
  },
709
- messageTitle: { fontFamily: theme.font.sans, fontSize: theme.fontSize[14], fontWeight: theme.fontWeight.bold, color: theme.color.text, textAlign: "center" },
710
- messageText: { fontFamily: theme.font.sans, fontSize: theme.fontSize[13], lineHeight: theme.space[19], color: theme.color.text3, textAlign: "center" },
889
+ messageTitle: {
890
+ fontFamily: theme.font.sans,
891
+ fontSize: theme.fontSize[14],
892
+ fontWeight: theme.fontWeight.bold,
893
+ color: theme.color.text,
894
+ textAlign: "center"
895
+ },
896
+ messageText: {
897
+ fontFamily: theme.font.sans,
898
+ fontSize: theme.fontSize[13],
899
+ lineHeight: theme.space[19],
900
+ color: theme.color.text3,
901
+ textAlign: "center"
902
+ },
711
903
  caption: {
712
904
  borderTopWidth: theme.borderWidth.base,
713
905
  borderTopColor: theme.color.border,
@@ -715,8 +907,16 @@ var stylesheet = createStyleSheet((theme) => ({
715
907
  paddingHorizontal: theme.space.s4,
716
908
  paddingVertical: theme.space.s2
717
909
  },
718
- captionText: { fontFamily: theme.font.mono, fontSize: theme.fontSize[11], color: theme.color.text3 },
719
- tableWrap: { borderTopWidth: theme.borderWidth.base, borderTopColor: theme.color.border, maxHeight: theme.space[256] },
910
+ captionText: {
911
+ fontFamily: theme.font.mono,
912
+ fontSize: theme.fontSize[11],
913
+ color: theme.color.text3
914
+ },
915
+ tableWrap: {
916
+ borderTopWidth: theme.borderWidth.base,
917
+ borderTopColor: theme.color.border,
918
+ maxHeight: theme.space[256]
919
+ },
720
920
  tableScroll: { maxHeight: theme.space[224] },
721
921
  tableCaption: {
722
922
  fontFamily: theme.font.mono,
@@ -749,7 +949,12 @@ var stylesheet = createStyleSheet((theme) => ({
749
949
  color: theme.color.text,
750
950
  textAlign: "right"
751
951
  },
752
- tdFirst: { textAlign: "left", minWidth: theme.space[120], fontWeight: theme.fontWeight.semibold, color: theme.color.text2 }
952
+ tdFirst: {
953
+ textAlign: "left",
954
+ minWidth: theme.space[120],
955
+ fontWeight: theme.fontWeight.semibold,
956
+ color: theme.color.text2
957
+ }
753
958
  }));
754
959
 
755
960
  export { Chart, ChartDataTable, SceneDefsNodes, SceneNodes, nativeChartPalette };
@@ -1,5 +1,6 @@
1
- import { camMeta, decorativeProps } from './chunk-RW6ZL2FQ.js';
2
- import { useReducedMotion } from './chunk-6N33LFQA.js';
1
+ import { useAnalyzerLabels, camMeta, decorativeProps } from './chunk-HJLPZA4X.js';
2
+ import { useLoamLocale } from './chunk-APCWFOZW.js';
3
+ import { useReducedMotion } from './chunk-J64KGCGX.js';
3
4
  import * as React from 'react';
4
5
  import { Animated, View, Text, Easing } from 'react-native';
5
6
  import Svg, { Defs, Pattern, Line, RadialGradient, Stop, Rect } from 'react-native-svg';
@@ -9,12 +10,14 @@ import { jsxs, jsx } from 'react/jsx-runtime';
9
10
 
10
11
  var PLACEHOLDER_LABEL = "live feed \xB7 placeholder";
11
12
  function PlaceholderFeed({
12
- label = PLACEHOLDER_LABEL,
13
+ label,
14
+ labels,
13
15
  drift = true,
14
16
  topInset = 0,
15
17
  children
16
18
  }) {
17
- const theme = useLoamTheme();
19
+ const theme = useLoamTheme("analyzer");
20
+ const t = useAnalyzerLabels(labels);
18
21
  const reduced = useReducedMotion();
19
22
  const { styles } = useStyles(feedSheet);
20
23
  const still = reduced || theme.reduceMotion || !drift;
@@ -89,7 +92,7 @@ function PlaceholderFeed({
89
92
  /* @__PURE__ */ jsx(Rect, { x: "0", y: "0", width: "100%", height: "100%", fill: "url(#loam-cam-vignette-fill)" })
90
93
  ] }) }),
91
94
  children,
92
- /* @__PURE__ */ jsx(Text, { style: [styles.label, camMeta(theme), topInset ? { marginTop: topInset } : null], children: label })
95
+ /* @__PURE__ */ jsx(Text, { style: [styles.label, camMeta(theme), topInset ? { marginTop: topInset } : null], children: label ?? t.placeholderFeed })
93
96
  ] });
94
97
  }
95
98
  var PLATE = {
@@ -102,10 +105,13 @@ var PLATE = {
102
105
  };
103
106
  function SubjectPlate({
104
107
  profile: profileProp,
105
- caption
108
+ caption,
109
+ labels
106
110
  }) {
107
- const theme = useLoamTheme();
111
+ const theme = useLoamTheme("analyzer");
108
112
  const { styles } = useStyles(feedSheet);
113
+ const t = useAnalyzerLabels(labels);
114
+ const locale = useLoamLocale();
109
115
  const p = profile(profileProp);
110
116
  const plate = PLATE[p.id] ?? PLATE.generic;
111
117
  return /* @__PURE__ */ jsx(
@@ -115,7 +121,7 @@ function SubjectPlate({
115
121
  testID: `loam-subject-plate-${p.id}`,
116
122
  style: [styles.subjectPlate, { width: plate.width, height: plate.height }],
117
123
  ...decorativeProps(),
118
- children: /* @__PURE__ */ jsx(Text, { style: [styles.subjectCaption, camMeta(theme)], children: (caption ?? plate.caption).toUpperCase() })
124
+ children: /* @__PURE__ */ jsx(Text, { style: [styles.subjectCaption, camMeta(theme)], children: (caption ?? t.plate[p.id] ?? plate.caption).toLocaleUpperCase(locale) })
119
125
  }
120
126
  );
121
127
  }