tempest-react-sdk 0.52.0 → 0.54.0

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 (507) hide show
  1. package/README.md +58 -7
  2. package/dist/access/Can.cjs +1 -1
  3. package/dist/access/Can.cjs.map +1 -1
  4. package/dist/access/Can.js +3 -3
  5. package/dist/access/Can.js.map +1 -1
  6. package/dist/audio/audio-bus.cjs +2 -0
  7. package/dist/audio/audio-bus.cjs.map +1 -0
  8. package/dist/audio/audio-bus.js +116 -0
  9. package/dist/audio/audio-bus.js.map +1 -0
  10. package/dist/audio/level-meter.cjs +1 -1
  11. package/dist/audio/level-meter.cjs.map +1 -1
  12. package/dist/audio/level-meter.js +15 -15
  13. package/dist/audio/level-meter.js.map +1 -1
  14. package/dist/audio/noise-floor.cjs +2 -0
  15. package/dist/audio/noise-floor.cjs.map +1 -0
  16. package/dist/audio/noise-floor.js +27 -0
  17. package/dist/audio/noise-floor.js.map +1 -0
  18. package/dist/audio/use-audio-bus.cjs +2 -0
  19. package/dist/audio/use-audio-bus.cjs.map +1 -0
  20. package/dist/audio/use-audio-bus.js +11 -0
  21. package/dist/audio/use-audio-bus.js.map +1 -0
  22. package/dist/audio/voice-activity.cjs +2 -0
  23. package/dist/audio/voice-activity.cjs.map +1 -0
  24. package/dist/audio/voice-activity.js +26 -0
  25. package/dist/audio/voice-activity.js.map +1 -0
  26. package/dist/audio/voice-chain-stages.cjs +2 -0
  27. package/dist/audio/voice-chain-stages.cjs.map +1 -0
  28. package/dist/audio/voice-chain-stages.js +82 -0
  29. package/dist/audio/voice-chain-stages.js.map +1 -0
  30. package/dist/audio/voice-chain.cjs +2 -0
  31. package/dist/audio/voice-chain.cjs.map +1 -0
  32. package/dist/audio/voice-chain.js +74 -0
  33. package/dist/audio/voice-chain.js.map +1 -0
  34. package/dist/auth/lazy-with-retry.cjs.map +1 -1
  35. package/dist/auth/lazy-with-retry.js.map +1 -1
  36. package/dist/auth/passkey.cjs.map +1 -1
  37. package/dist/auth/passkey.js.map +1 -1
  38. package/dist/br/BrazilStateCitySelect.cjs +1 -1
  39. package/dist/br/BrazilStateCitySelect.cjs.map +1 -1
  40. package/dist/br/BrazilStateCitySelect.js +36 -28
  41. package/dist/br/BrazilStateCitySelect.js.map +1 -1
  42. package/dist/br/data/br-centroids.cjs +1 -1
  43. package/dist/br/data/br-centroids.cjs.map +1 -1
  44. package/dist/br/data/br-centroids.js +11105 -11045
  45. package/dist/br/data/br-centroids.js.map +1 -1
  46. package/dist/br/data/br-locations.cjs +1 -1
  47. package/dist/br/data/br-locations.cjs.map +1 -1
  48. package/dist/br/data/br-locations.js +5803 -137
  49. package/dist/br/data/br-locations.js.map +1 -1
  50. package/dist/br/data/br-uf-geo.cjs +1 -1
  51. package/dist/br/data/br-uf-geo.cjs.map +1 -1
  52. package/dist/br/data/br-uf-geo.js +5721 -6777
  53. package/dist/br/data/br-uf-geo.js.map +1 -1
  54. package/dist/br/data/mun/AC.cjs +1 -1
  55. package/dist/br/data/mun/AC.cjs.map +1 -1
  56. package/dist/br/data/mun/AC.js +681 -689
  57. package/dist/br/data/mun/AC.js.map +1 -1
  58. package/dist/br/data/mun/AL.cjs +1 -1
  59. package/dist/br/data/mun/AL.cjs.map +1 -1
  60. package/dist/br/data/mun/AL.js +949 -844
  61. package/dist/br/data/mun/AL.js.map +1 -1
  62. package/dist/br/data/mun/AM.cjs +1 -1
  63. package/dist/br/data/mun/AM.cjs.map +1 -1
  64. package/dist/br/data/mun/AM.js +4337 -4218
  65. package/dist/br/data/mun/AM.js.map +1 -1
  66. package/dist/br/data/mun/AP.cjs +1 -1
  67. package/dist/br/data/mun/AP.cjs.map +1 -1
  68. package/dist/br/data/mun/AP.js +786 -780
  69. package/dist/br/data/mun/AP.js.map +1 -1
  70. package/dist/br/data/mun/BA.cjs +1 -1
  71. package/dist/br/data/mun/BA.cjs.map +1 -1
  72. package/dist/br/data/mun/BA.js +6329 -5633
  73. package/dist/br/data/mun/BA.js.map +1 -1
  74. package/dist/br/data/mun/CE.cjs +1 -1
  75. package/dist/br/data/mun/CE.cjs.map +1 -1
  76. package/dist/br/data/mun/CE.js +2544 -2487
  77. package/dist/br/data/mun/CE.js.map +1 -1
  78. package/dist/br/data/mun/DF.cjs +1 -1
  79. package/dist/br/data/mun/DF.cjs.map +1 -1
  80. package/dist/br/data/mun/DF.js +17 -16
  81. package/dist/br/data/mun/DF.js.map +1 -1
  82. package/dist/br/data/mun/ES.cjs +1 -1
  83. package/dist/br/data/mun/ES.cjs.map +1 -1
  84. package/dist/br/data/mun/ES.js +1101 -1070
  85. package/dist/br/data/mun/ES.js.map +1 -1
  86. package/dist/br/data/mun/GO.cjs +1 -1
  87. package/dist/br/data/mun/GO.cjs.map +1 -1
  88. package/dist/br/data/mun/GO.js +4632 -4636
  89. package/dist/br/data/mun/GO.js.map +1 -1
  90. package/dist/br/data/mun/MA.cjs +1 -1
  91. package/dist/br/data/mun/MA.cjs.map +1 -1
  92. package/dist/br/data/mun/MA.js +3603 -3457
  93. package/dist/br/data/mun/MA.js.map +1 -1
  94. package/dist/br/data/mun/MG.cjs +1 -1
  95. package/dist/br/data/mun/MG.cjs.map +1 -1
  96. package/dist/br/data/mun/MG.js +12716 -11739
  97. package/dist/br/data/mun/MG.js.map +1 -1
  98. package/dist/br/data/mun/MS.cjs +1 -1
  99. package/dist/br/data/mun/MS.cjs.map +1 -1
  100. package/dist/br/data/mun/MS.js +2182 -2335
  101. package/dist/br/data/mun/MS.js.map +1 -1
  102. package/dist/br/data/mun/MT.cjs +1 -1
  103. package/dist/br/data/mun/MT.cjs.map +1 -1
  104. package/dist/br/data/mun/MT.js +4808 -4896
  105. package/dist/br/data/mun/MT.js.map +1 -1
  106. package/dist/br/data/mun/PA.cjs +1 -1
  107. package/dist/br/data/mun/PA.cjs.map +1 -1
  108. package/dist/br/data/mun/PA.js +4981 -4901
  109. package/dist/br/data/mun/PA.js.map +1 -1
  110. package/dist/br/data/mun/PB.cjs +1 -1
  111. package/dist/br/data/mun/PB.cjs.map +1 -1
  112. package/dist/br/data/mun/PB.js +2418 -1956
  113. package/dist/br/data/mun/PB.js.map +1 -1
  114. package/dist/br/data/mun/PE.cjs +1 -1
  115. package/dist/br/data/mun/PE.cjs.map +1 -1
  116. package/dist/br/data/mun/PE.js +2164 -1987
  117. package/dist/br/data/mun/PE.js.map +1 -1
  118. package/dist/br/data/mun/PI.cjs +1 -1
  119. package/dist/br/data/mun/PI.cjs.map +1 -1
  120. package/dist/br/data/mun/PI.js +2982 -2844
  121. package/dist/br/data/mun/PI.js.map +1 -1
  122. package/dist/br/data/mun/PR.cjs +1 -1
  123. package/dist/br/data/mun/PR.cjs.map +1 -1
  124. package/dist/br/data/mun/PR.js +5425 -5240
  125. package/dist/br/data/mun/PR.js.map +1 -1
  126. package/dist/br/data/mun/RJ.cjs +1 -1
  127. package/dist/br/data/mun/RJ.cjs.map +1 -1
  128. package/dist/br/data/mun/RJ.js +1395 -1178
  129. package/dist/br/data/mun/RJ.js.map +1 -1
  130. package/dist/br/data/mun/RN.cjs +1 -1
  131. package/dist/br/data/mun/RN.cjs.map +1 -1
  132. package/dist/br/data/mun/RN.js +1608 -1382
  133. package/dist/br/data/mun/RN.js.map +1 -1
  134. package/dist/br/data/mun/RO.cjs +1 -1
  135. package/dist/br/data/mun/RO.cjs.map +1 -1
  136. package/dist/br/data/mun/RO.js +1392 -1470
  137. package/dist/br/data/mun/RO.js.map +1 -1
  138. package/dist/br/data/mun/RR.cjs +1 -1
  139. package/dist/br/data/mun/RR.cjs.map +1 -1
  140. package/dist/br/data/mun/RR.js +795 -778
  141. package/dist/br/data/mun/RR.js.map +1 -1
  142. package/dist/br/data/mun/RS.cjs +1 -1
  143. package/dist/br/data/mun/RS.cjs.map +1 -1
  144. package/dist/br/data/mun/RS.js +7579 -6424
  145. package/dist/br/data/mun/RS.js.map +1 -1
  146. package/dist/br/data/mun/SC.cjs +1 -1
  147. package/dist/br/data/mun/SC.cjs.map +1 -1
  148. package/dist/br/data/mun/SC.js +3979 -3357
  149. package/dist/br/data/mun/SC.js.map +1 -1
  150. package/dist/br/data/mun/SE.cjs +1 -1
  151. package/dist/br/data/mun/SE.cjs.map +1 -1
  152. package/dist/br/data/mun/SE.js +812 -625
  153. package/dist/br/data/mun/SE.js.map +1 -1
  154. package/dist/br/data/mun/SP.cjs +1 -1
  155. package/dist/br/data/mun/SP.cjs.map +1 -1
  156. package/dist/br/data/mun/SP.js +7866 -6803
  157. package/dist/br/data/mun/SP.js.map +1 -1
  158. package/dist/br/data/mun/TO.cjs +1 -1
  159. package/dist/br/data/mun/TO.cjs.map +1 -1
  160. package/dist/br/data/mun/TO.js +2763 -2817
  161. package/dist/br/data/mun/TO.js.map +1 -1
  162. package/dist/br/locations.cjs +1 -1
  163. package/dist/br/locations.cjs.map +1 -1
  164. package/dist/br/locations.js +97 -24
  165. package/dist/br/locations.js.map +1 -1
  166. package/dist/br/scales.cjs +1 -1
  167. package/dist/br/scales.cjs.map +1 -1
  168. package/dist/br/scales.js +8 -4
  169. package/dist/br/scales.js.map +1 -1
  170. package/dist/br/whatsapp.cjs +2 -0
  171. package/dist/br/whatsapp.cjs.map +1 -0
  172. package/dist/br/whatsapp.js +21 -0
  173. package/dist/br/whatsapp.js.map +1 -0
  174. package/dist/br.cjs +1 -1
  175. package/dist/br.cjs.map +1 -1
  176. package/dist/br.d.ts +188 -10
  177. package/dist/br.js +18 -17
  178. package/dist/br.js.map +1 -1
  179. package/dist/components/BottomSheet/BottomSheet.cjs +1 -1
  180. package/dist/components/BottomSheet/BottomSheet.cjs.map +1 -1
  181. package/dist/components/BottomSheet/BottomSheet.js +30 -27
  182. package/dist/components/BottomSheet/BottomSheet.js.map +1 -1
  183. package/dist/components/Command/Command.cjs +1 -1
  184. package/dist/components/Command/Command.cjs.map +1 -1
  185. package/dist/components/Command/Command.js +78 -75
  186. package/dist/components/Command/Command.js.map +1 -1
  187. package/dist/components/Drawer/Drawer.cjs +1 -1
  188. package/dist/components/Drawer/Drawer.cjs.map +1 -1
  189. package/dist/components/Drawer/Drawer.js +42 -39
  190. package/dist/components/Drawer/Drawer.js.map +1 -1
  191. package/dist/components/DropdownMenu/DropdownMenu.cjs +1 -1
  192. package/dist/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
  193. package/dist/components/DropdownMenu/DropdownMenu.js +111 -67
  194. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  195. package/dist/components/Modal/Modal.cjs +1 -1
  196. package/dist/components/Modal/Modal.cjs.map +1 -1
  197. package/dist/components/Modal/Modal.js +45 -42
  198. package/dist/components/Modal/Modal.js.map +1 -1
  199. package/dist/components/Money/Money.cjs +1 -1
  200. package/dist/components/Money/Money.cjs.map +1 -1
  201. package/dist/components/Money/Money.js +10 -9
  202. package/dist/components/Money/Money.js.map +1 -1
  203. package/dist/components/Pagination/Pagination.cjs +1 -1
  204. package/dist/components/Pagination/Pagination.cjs.map +1 -1
  205. package/dist/components/Pagination/Pagination.js +38 -31
  206. package/dist/components/Pagination/Pagination.js.map +1 -1
  207. package/dist/components/Pagination/Pagination.module.cjs +1 -1
  208. package/dist/components/Pagination/Pagination.module.cjs.map +1 -1
  209. package/dist/components/Pagination/Pagination.module.js +4 -4
  210. package/dist/components/Pagination/Pagination.module.js.map +1 -1
  211. package/dist/components/Portal/Portal.cjs +1 -1
  212. package/dist/components/Portal/Portal.cjs.map +1 -1
  213. package/dist/components/Portal/Portal.js +9 -6
  214. package/dist/components/Portal/Portal.js.map +1 -1
  215. package/dist/components/Portal/portal-host.cjs +2 -0
  216. package/dist/components/Portal/portal-host.cjs.map +1 -0
  217. package/dist/components/Portal/portal-host.js +11 -0
  218. package/dist/components/Portal/portal-host.js.map +1 -0
  219. package/dist/components/RangeSlider/RangeSlider.cjs +1 -1
  220. package/dist/components/RangeSlider/RangeSlider.cjs.map +1 -1
  221. package/dist/components/RangeSlider/RangeSlider.js +23 -23
  222. package/dist/components/RangeSlider/RangeSlider.js.map +1 -1
  223. package/dist/components/Scheduler/Scheduler.cjs +1 -1
  224. package/dist/components/Scheduler/Scheduler.cjs.map +1 -1
  225. package/dist/components/Scheduler/Scheduler.js +83 -82
  226. package/dist/components/Scheduler/Scheduler.js.map +1 -1
  227. package/dist/components/Slider/Slider.cjs +1 -1
  228. package/dist/components/Slider/Slider.cjs.map +1 -1
  229. package/dist/components/Slider/Slider.js +9 -9
  230. package/dist/components/Slider/Slider.js.map +1 -1
  231. package/dist/components/Toast/ToastProvider.cjs +1 -1
  232. package/dist/components/Toast/ToastProvider.cjs.map +1 -1
  233. package/dist/components/Toast/ToastProvider.js +55 -53
  234. package/dist/components/Toast/ToastProvider.js.map +1 -1
  235. package/dist/components/VirtualList/VirtualList.cjs +1 -1
  236. package/dist/components/VirtualList/VirtualList.cjs.map +1 -1
  237. package/dist/components/VirtualList/VirtualList.js +41 -31
  238. package/dist/components/VirtualList/VirtualList.js.map +1 -1
  239. package/dist/components/VirtualTable/VirtualTable.cjs +1 -1
  240. package/dist/components/VirtualTable/VirtualTable.cjs.map +1 -1
  241. package/dist/components/VirtualTable/VirtualTable.js +78 -68
  242. package/dist/components/VirtualTable/VirtualTable.js.map +1 -1
  243. package/dist/forms/FormField.cjs +1 -1
  244. package/dist/forms/FormField.cjs.map +1 -1
  245. package/dist/forms/FormField.js +23 -21
  246. package/dist/forms/FormField.js.map +1 -1
  247. package/dist/forms/masked-inputs.cjs +1 -1
  248. package/dist/forms/masked-inputs.cjs.map +1 -1
  249. package/dist/forms/masked-inputs.js +20 -19
  250. package/dist/forms/masked-inputs.js.map +1 -1
  251. package/dist/hooks/use-fullscreen-element.cjs +2 -0
  252. package/dist/hooks/use-fullscreen-element.cjs.map +1 -0
  253. package/dist/hooks/use-fullscreen-element.js +20 -0
  254. package/dist/hooks/use-fullscreen-element.js.map +1 -0
  255. package/dist/hooks/use-fullscreen.cjs +2 -0
  256. package/dist/hooks/use-fullscreen.cjs.map +1 -0
  257. package/dist/hooks/use-fullscreen.js +66 -0
  258. package/dist/hooks/use-fullscreen.js.map +1 -0
  259. package/dist/hooks/use-push-to-talk.cjs +2 -0
  260. package/dist/hooks/use-push-to-talk.cjs.map +1 -0
  261. package/dist/hooks/use-push-to-talk.js +61 -0
  262. package/dist/hooks/use-push-to-talk.js.map +1 -0
  263. package/dist/http/describe-api-error.cjs.map +1 -1
  264. package/dist/http/describe-api-error.js.map +1 -1
  265. package/dist/http/errors.cjs +1 -1
  266. package/dist/http/errors.cjs.map +1 -1
  267. package/dist/http/errors.js +34 -16
  268. package/dist/http/errors.js.map +1 -1
  269. package/dist/http/parse-response.cjs +2 -2
  270. package/dist/http/parse-response.cjs.map +1 -1
  271. package/dist/http/parse-response.js +9 -8
  272. package/dist/http/parse-response.js.map +1 -1
  273. package/dist/i18n/create-i18n.cjs +1 -1
  274. package/dist/i18n/create-i18n.cjs.map +1 -1
  275. package/dist/i18n/create-i18n.js +28 -27
  276. package/dist/i18n/create-i18n.js.map +1 -1
  277. package/dist/query/QueryProvider.cjs +1 -1
  278. package/dist/query/QueryProvider.cjs.map +1 -1
  279. package/dist/query/QueryProvider.js +13 -11
  280. package/dist/query/QueryProvider.js.map +1 -1
  281. package/dist/query/foreign-client-warning.cjs +2 -0
  282. package/dist/query/foreign-client-warning.cjs.map +1 -0
  283. package/dist/query/foreign-client-warning.js +12 -0
  284. package/dist/query/foreign-client-warning.js.map +1 -0
  285. package/dist/router/AppRouter.cjs +1 -1
  286. package/dist/router/AppRouter.cjs.map +1 -1
  287. package/dist/router/AppRouter.js +28 -21
  288. package/dist/router/AppRouter.js.map +1 -1
  289. package/dist/router/RouteGuard.cjs +1 -1
  290. package/dist/router/RouteGuard.cjs.map +1 -1
  291. package/dist/router/RouteGuard.js +4 -4
  292. package/dist/router/RouteGuard.js.map +1 -1
  293. package/dist/sse/create-event-stream.cjs +1 -1
  294. package/dist/sse/create-event-stream.cjs.map +1 -1
  295. package/dist/sse/create-event-stream.js +34 -38
  296. package/dist/sse/create-event-stream.js.map +1 -1
  297. package/dist/styles/AIChat.css +79 -0
  298. package/dist/styles/Accordion.css +12 -0
  299. package/dist/styles/Alert.css +32 -0
  300. package/dist/styles/AppBar.css +17 -0
  301. package/dist/styles/AppShell.css +8 -0
  302. package/dist/styles/AspectRatio.css +3 -0
  303. package/dist/styles/AudioPlayer.css +13 -0
  304. package/dist/styles/AudioRecorder.css +20 -0
  305. package/dist/styles/Avatar.css +13 -0
  306. package/dist/styles/AvatarGroup.css +18 -0
  307. package/dist/styles/Badge.css +25 -0
  308. package/dist/styles/Banner.css +13 -0
  309. package/dist/styles/BarList.css +10 -0
  310. package/dist/styles/BarcodeScanner.css +21 -0
  311. package/dist/styles/BottomNavigation.css +10 -0
  312. package/dist/styles/BottomSheet.css +11 -0
  313. package/dist/styles/BrazilMap.css +20 -0
  314. package/dist/styles/Breadcrumbs.css +8 -0
  315. package/dist/styles/Button.css +42 -0
  316. package/dist/styles/Calendar.css +16 -0
  317. package/dist/styles/Card.css +15 -0
  318. package/dist/styles/Carousel.css +17 -0
  319. package/dist/styles/Center.css +5 -0
  320. package/dist/styles/Chat.css +35 -0
  321. package/dist/styles/Checkbox.css +11 -0
  322. package/dist/styles/ChipInput.css +13 -0
  323. package/dist/styles/CodeBlock.css +25 -0
  324. package/dist/styles/Collapsible.css +6 -0
  325. package/dist/styles/Combobox.css +18 -0
  326. package/dist/styles/Command.css +20 -0
  327. package/dist/styles/ContextMenu.css +11 -0
  328. package/dist/styles/CopyButton.css +4 -0
  329. package/dist/styles/DataList.css +3 -0
  330. package/dist/styles/DataTable.css +19 -0
  331. package/dist/styles/DateRangePicker.css +22 -0
  332. package/dist/styles/DescriptionList.css +4 -0
  333. package/dist/styles/Divider.css +11 -0
  334. package/dist/styles/Drawer.css +22 -0
  335. package/dist/styles/DropdownMenu.css +16 -0
  336. package/dist/styles/Dropzone.css +7 -0
  337. package/dist/styles/EmptyState.css +6 -0
  338. package/dist/styles/ErrorState.css +6 -0
  339. package/dist/styles/ErrorText.css +2 -0
  340. package/dist/styles/FileUpload.css +17 -0
  341. package/dist/styles/FilterBar.css +19 -0
  342. package/dist/styles/FloatingActionButton.css +23 -0
  343. package/dist/styles/Form.css +21 -0
  344. package/dist/styles/HoverCard.css +11 -0
  345. package/dist/styles/IconPicker.css +6 -0
  346. package/dist/styles/Image.css +2 -0
  347. package/dist/styles/ImageCropper.css +16 -0
  348. package/dist/styles/Input.css +24 -0
  349. package/dist/styles/InstallBanner.css +8 -0
  350. package/dist/styles/Kanban.css +15 -0
  351. package/dist/styles/Kbd.css +5 -0
  352. package/dist/styles/Label.css +3 -0
  353. package/dist/styles/Layout.css +22 -0
  354. package/dist/styles/Lightbox.css +21 -0
  355. package/dist/styles/ListTile.css +14 -0
  356. package/dist/styles/MapLegend.css +9 -0
  357. package/dist/styles/Markdown.css +24 -0
  358. package/dist/styles/Masonry.css +4 -0
  359. package/dist/styles/Menubar.css +17 -0
  360. package/dist/styles/Modal.css +21 -0
  361. package/dist/styles/ModalsManager.css +2 -0
  362. package/dist/styles/MultiSelect.css +21 -0
  363. package/dist/styles/MunicipalitySearch.css +6 -0
  364. package/dist/styles/NProgress.css +2 -0
  365. package/dist/styles/Navbar.css +10 -0
  366. package/dist/styles/NavigationMenu.css +12 -0
  367. package/dist/styles/NavigationRail.css +14 -0
  368. package/dist/styles/NotificationCenter.css +21 -0
  369. package/dist/styles/OfflineIndicator.css +7 -0
  370. package/dist/styles/Page.css +13 -0
  371. package/dist/styles/Pagination.css +12 -0
  372. package/dist/styles/PasswordInput.css +21 -0
  373. package/dist/styles/PinInput.css +13 -0
  374. package/dist/styles/PixQRCode.css +9 -0
  375. package/dist/styles/Popover.css +10 -0
  376. package/dist/styles/Progress.css +11 -0
  377. package/dist/styles/QRCode.css +3 -0
  378. package/dist/styles/Radio.css +14 -0
  379. package/dist/styles/RangeSlider.css +15 -0
  380. package/dist/styles/RatingStars.css +11 -0
  381. package/dist/styles/RefreshIndicator.css +5 -0
  382. package/dist/styles/Resizable.css +13 -0
  383. package/dist/styles/RichTextEditor.css +19 -0
  384. package/dist/styles/SafeArea.css +7 -0
  385. package/dist/styles/Scheduler.css +24 -0
  386. package/dist/styles/ScrollArea.css +7 -0
  387. package/dist/styles/SearchBar.css +11 -0
  388. package/dist/styles/SegmentedControl.css +12 -0
  389. package/dist/styles/Select.css +14 -0
  390. package/dist/styles/Sidebar.css +19 -0
  391. package/dist/styles/SignaturePad.css +6 -0
  392. package/dist/styles/Skeleton.css +7 -0
  393. package/dist/styles/Slider.css +15 -0
  394. package/dist/styles/Spacer.css +4 -0
  395. package/dist/styles/Sparkline.css +4 -0
  396. package/dist/styles/Spinner.css +12 -0
  397. package/dist/styles/Stat.css +12 -0
  398. package/dist/styles/Stepper.css +17 -0
  399. package/dist/styles/StepperInput.css +15 -0
  400. package/dist/styles/Switch.css +11 -0
  401. package/dist/styles/SyncStatusBadge.css +13 -0
  402. package/dist/styles/Table.css +16 -0
  403. package/dist/styles/Tabs.css +14 -0
  404. package/dist/styles/Tag.css +14 -0
  405. package/dist/styles/Textarea.css +13 -0
  406. package/dist/styles/TimePicker.css +14 -0
  407. package/dist/styles/Timeline.css +17 -0
  408. package/dist/styles/Toast.css +21 -0
  409. package/dist/styles/Toggle.css +12 -0
  410. package/dist/styles/ToggleGroup.css +9 -0
  411. package/dist/styles/Tooltip.css +10 -0
  412. package/dist/styles/Tour.css +20 -0
  413. package/dist/styles/TrajectoryMap.css +16 -0
  414. package/dist/styles/Transfer.css +21 -0
  415. package/dist/styles/TreeView.css +17 -0
  416. package/dist/styles/TruncateText.css +2 -0
  417. package/dist/styles/UpdatePrompt.css +10 -0
  418. package/dist/styles/VirtualList.css +5 -0
  419. package/dist/styles/VirtualTable.css +17 -0
  420. package/dist/styles/VisuallyHidden.css +2 -0
  421. package/dist/styles/Wizard.css +4 -0
  422. package/dist/styles/actions.css +104 -0
  423. package/dist/styles/advanced.css +66 -0
  424. package/dist/styles/br.css +41 -0
  425. package/dist/styles/chat.css +113 -0
  426. package/dist/styles/core.css +40 -0
  427. package/dist/styles/data.css +222 -0
  428. package/dist/styles/editor.css +19 -0
  429. package/dist/styles/feedback.css +201 -0
  430. package/dist/styles/forms.css +321 -0
  431. package/dist/styles/geo.css +16 -0
  432. package/dist/styles/icons.css +6 -0
  433. package/dist/styles/identity.css +48 -0
  434. package/dist/styles/layout.css +122 -0
  435. package/dist/styles/media.css +52 -0
  436. package/dist/styles/navigation.css +167 -0
  437. package/dist/styles/overlay.css +73 -0
  438. package/dist/styles/utility.css +39 -0
  439. package/dist/styles.css +1 -1
  440. package/dist/sw/register-service-worker.cjs +1 -1
  441. package/dist/sw/register-service-worker.cjs.map +1 -1
  442. package/dist/sw/register-service-worker.js +21 -17
  443. package/dist/sw/register-service-worker.js.map +1 -1
  444. package/dist/sw.d.ts +17 -1
  445. package/dist/tempest-react-sdk.cjs +1 -1
  446. package/dist/tempest-react-sdk.d.ts +1382 -76
  447. package/dist/tempest-react-sdk.js +293 -281
  448. package/dist/utils/dev-mode.cjs.map +1 -1
  449. package/dist/utils/dev-mode.js.map +1 -1
  450. package/dist/utils/duplicate-instance.cjs +2 -0
  451. package/dist/utils/duplicate-instance.cjs.map +1 -0
  452. package/dist/utils/duplicate-instance.js +6 -0
  453. package/dist/utils/duplicate-instance.js.map +1 -0
  454. package/dist/utils/format.cjs +1 -1
  455. package/dist/utils/format.cjs.map +1 -1
  456. package/dist/utils/format.js +22 -14
  457. package/dist/utils/format.js.map +1 -1
  458. package/dist/utils/intl-cache.cjs +2 -0
  459. package/dist/utils/intl-cache.cjs.map +1 -0
  460. package/dist/utils/intl-cache.js +23 -0
  461. package/dist/utils/intl-cache.js.map +1 -0
  462. package/dist/utils/json-frame.cjs +2 -0
  463. package/dist/utils/json-frame.cjs.map +1 -0
  464. package/dist/utils/json-frame.js +30 -0
  465. package/dist/utils/json-frame.js.map +1 -0
  466. package/dist/utils/numbers.cjs +1 -1
  467. package/dist/utils/numbers.cjs.map +1 -1
  468. package/dist/utils/numbers.js +8 -7
  469. package/dist/utils/numbers.js.map +1 -1
  470. package/dist/vision/results.cjs +1 -1
  471. package/dist/vision/results.cjs.map +1 -1
  472. package/dist/vision/results.js +26 -17
  473. package/dist/vision/results.js.map +1 -1
  474. package/dist/vision.d.ts +29 -0
  475. package/dist/vite/tempest-icons.cjs +1 -1
  476. package/dist/vite/tempest-icons.cjs.map +1 -1
  477. package/dist/vite/tempest-icons.js +1 -1
  478. package/dist/vite/tempest-icons.js.map +1 -1
  479. package/dist/webrtc/link-stats.cjs +2 -0
  480. package/dist/webrtc/link-stats.cjs.map +1 -0
  481. package/dist/webrtc/link-stats.js +74 -0
  482. package/dist/webrtc/link-stats.js.map +1 -0
  483. package/dist/webrtc/opus-sdp.cjs +3 -0
  484. package/dist/webrtc/opus-sdp.cjs.map +1 -0
  485. package/dist/webrtc/opus-sdp.js +94 -0
  486. package/dist/webrtc/opus-sdp.js.map +1 -0
  487. package/dist/webrtc/sender-bitrate.cjs +2 -0
  488. package/dist/webrtc/sender-bitrate.cjs.map +1 -0
  489. package/dist/webrtc/sender-bitrate.js +15 -0
  490. package/dist/webrtc/sender-bitrate.js.map +1 -0
  491. package/dist/webrtc/use-link-stats.cjs +2 -0
  492. package/dist/webrtc/use-link-stats.cjs.map +1 -0
  493. package/dist/webrtc/use-link-stats.js +22 -0
  494. package/dist/webrtc/use-link-stats.js.map +1 -0
  495. package/dist/ws/create-web-socket.cjs +1 -1
  496. package/dist/ws/create-web-socket.cjs.map +1 -1
  497. package/dist/ws/create-web-socket.js +130 -58
  498. package/dist/ws/create-web-socket.js.map +1 -1
  499. package/dist/ws/resilience.cjs +2 -0
  500. package/dist/ws/resilience.cjs.map +1 -0
  501. package/dist/ws/resilience.js +21 -0
  502. package/dist/ws/resilience.js.map +1 -0
  503. package/dist/ws/use-web-socket.cjs +1 -1
  504. package/dist/ws/use-web-socket.cjs.map +1 -1
  505. package/dist/ws/use-web-socket.js +47 -39
  506. package/dist/ws/use-web-socket.js.map +1 -1
  507. package/package.json +5 -2
@@ -1,109 +1,119 @@
1
1
  import { cn as e } from "../../utils/cn.js";
2
2
  import { compareValues as t } from "../../utils/compare-values.js";
3
3
  import n from "./VirtualTable.module.js";
4
- import { useCallback as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
5
- import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
4
+ import { memo as r, useCallback as i, useEffect as a, useMemo as o, useRef as s, useState as c } from "react";
5
+ import { Fragment as l, jsx as u, jsxs as d } from "react/jsx-runtime";
6
6
  //#region src/components/VirtualTable/VirtualTable.tsx
7
- function d(e) {
7
+ function f(e) {
8
8
  if (e === "right") return n.alignRight;
9
9
  if (e === "center") return n.alignCenter;
10
10
  }
11
- function f({ data: f, columns: p, rowHeight: m, height: h, overscan: g = 4, rowKey: _, initialSort: v, onRowClick: y, emptyMessage: b = "Nenhum registro encontrado.", caption: x, scrollToIndex: S, className: C, ...w }) {
12
- let T = o(null), [E, D] = s(0), [O, k] = s(0), [A, j] = s(v ?? null);
13
- i(() => {
14
- let e = T.current;
15
- if (!e || (k(e.clientHeight), typeof ResizeObserver > "u")) return;
16
- let t = new ResizeObserver(() => k(e.clientHeight));
11
+ function p({ row: t, index: r, rowHeight: i, columns: a, onRowClick: o }) {
12
+ return /* @__PURE__ */ u("tr", {
13
+ "aria-rowindex": r + 1,
14
+ className: e(n.tr, o && n.clickable),
15
+ style: { height: i },
16
+ tabIndex: o ? 0 : void 0,
17
+ onClick: o ? () => o(t, r) : void 0,
18
+ onKeyDown: o ? (e) => {
19
+ (e.key === "Enter" || e.key === " ") && (e.preventDefault(), o(t, r));
20
+ } : void 0,
21
+ children: a.map((i) => /* @__PURE__ */ u("td", {
22
+ className: e(n.td, f(i.align)),
23
+ style: { width: i.width },
24
+ children: i.render ? i.render(t, r) : t[i.key] ?? null
25
+ }, String(i.key)))
26
+ });
27
+ }
28
+ var m = r(p);
29
+ function h({ data: r, columns: p, rowHeight: h, height: g, overscan: _ = 4, rowKey: v, initialSort: y, onRowClick: b, emptyMessage: x = "Nenhum registro encontrado.", caption: S, scrollToIndex: C, className: w, ...T }) {
30
+ let E = s(null), [D, O] = c(0), [k, A] = c(0), [j, M] = c(y ?? null);
31
+ a(() => {
32
+ let e = E.current;
33
+ if (!e || (A(e.clientHeight), typeof ResizeObserver > "u")) return;
34
+ let t = new ResizeObserver(() => A(e.clientHeight));
17
35
  return t.observe(e), () => t.disconnect();
18
- }, []), i(() => {
19
- let e = T.current;
20
- !e || S == null || (e.scrollTop = Math.max(0, Math.min(S, f.length - 1)) * m);
36
+ }, []), a(() => {
37
+ let e = E.current;
38
+ !e || C == null || (e.scrollTop = Math.max(0, Math.min(C, r.length - 1)) * h);
21
39
  }, [
22
- S,
23
- m,
24
- f.length
40
+ C,
41
+ h,
42
+ r.length
25
43
  ]);
26
- let M = a(() => {
27
- if (!A) return f;
28
- let e = A.direction === "asc" ? 1 : -1;
29
- return [...f].sort((n, r) => t(n[A.key], r[A.key]) * e);
30
- }, [f, A]), N = Math.max(0, Math.floor(E / m) - g), P = Math.ceil(O / m) + g * 2, F = Math.min(M.length, N + P), I = M.slice(N, F), L = r((e) => {
31
- j((t) => !t || t.key !== e ? {
44
+ let N = o(() => {
45
+ if (!j) return r;
46
+ let e = j.direction === "asc" ? 1 : -1;
47
+ return [...r].sort((n, r) => t(n[j.key], r[j.key]) * e);
48
+ }, [r, j]), P = Math.max(0, Math.floor(D / h) - _), F = Math.ceil(k / h) + _ * 2, I = Math.min(N.length, P + F), L = N.slice(P, I), R = i((e) => {
49
+ M((t) => !t || t.key !== e ? {
32
50
  key: e,
33
51
  direction: "asc"
34
52
  } : t.direction === "asc" ? {
35
53
  key: e,
36
54
  direction: "desc"
37
55
  } : null);
38
- let t = T.current;
39
- t && (t.scrollTop = 0), D(0);
56
+ let t = E.current;
57
+ t && (t.scrollTop = 0), O(0);
40
58
  }, []);
41
- return /* @__PURE__ */ l("div", {
42
- ref: T,
43
- className: e(n.scroll, C),
44
- style: { height: h },
45
- onScroll: (e) => D(e.currentTarget.scrollTop),
46
- ...w,
47
- children: /* @__PURE__ */ u("table", {
59
+ return /* @__PURE__ */ u("div", {
60
+ ref: E,
61
+ className: e(n.scroll, w),
62
+ style: { height: g },
63
+ onScroll: (e) => O(e.currentTarget.scrollTop),
64
+ ...T,
65
+ children: /* @__PURE__ */ d("table", {
48
66
  className: n.table,
49
- "aria-rowcount": M.length,
67
+ "aria-rowcount": N.length,
50
68
  children: [
51
- x ? /* @__PURE__ */ l("caption", {
69
+ S ? /* @__PURE__ */ u("caption", {
52
70
  className: n.caption,
53
- children: x
71
+ children: S
54
72
  }) : null,
55
- /* @__PURE__ */ l("thead", {
73
+ /* @__PURE__ */ u("thead", {
56
74
  className: n.head,
57
- children: /* @__PURE__ */ l("tr", { children: p.map((t) => {
58
- let r = A?.key === t.key;
59
- return /* @__PURE__ */ l("th", {
75
+ children: /* @__PURE__ */ u("tr", { children: p.map((t) => {
76
+ let r = j?.key === t.key;
77
+ return /* @__PURE__ */ u("th", {
60
78
  scope: "col",
61
- className: e(n.th, d(t.align)),
79
+ className: e(n.th, f(t.align)),
62
80
  style: { width: t.width },
63
- "aria-sort": r ? A?.direction === "asc" ? "ascending" : "descending" : t.sortable ? "none" : void 0,
64
- children: t.sortable ? /* @__PURE__ */ u("button", {
81
+ "aria-sort": r ? j?.direction === "asc" ? "ascending" : "descending" : t.sortable ? "none" : void 0,
82
+ children: t.sortable ? /* @__PURE__ */ d("button", {
65
83
  type: "button",
66
84
  className: n.sortButton,
67
- onClick: () => L(t.key),
68
- children: [t.header, /* @__PURE__ */ l("span", {
85
+ onClick: () => R(t.key),
86
+ children: [t.header, /* @__PURE__ */ u("span", {
69
87
  className: n.sortIndicator,
70
88
  "aria-hidden": !0,
71
- children: r ? A?.direction === "asc" ? "▲" : "▼" : "↕"
89
+ children: r ? j?.direction === "asc" ? "▲" : "▼" : "↕"
72
90
  })]
73
91
  }) : t.header
74
92
  }, String(t.key));
75
93
  }) })
76
94
  }),
77
- /* @__PURE__ */ l("tbody", { children: M.length === 0 ? /* @__PURE__ */ l("tr", { children: /* @__PURE__ */ l("td", {
95
+ /* @__PURE__ */ u("tbody", { children: N.length === 0 ? /* @__PURE__ */ u("tr", { children: /* @__PURE__ */ u("td", {
78
96
  className: n.emptyRow,
79
97
  colSpan: p.length,
80
- children: b
81
- }) }) : /* @__PURE__ */ u(c, { children: [
82
- N > 0 && /* @__PURE__ */ l("tr", {
98
+ children: x
99
+ }) }) : /* @__PURE__ */ d(l, { children: [
100
+ P > 0 && /* @__PURE__ */ u("tr", {
83
101
  "aria-hidden": !0,
84
- style: { height: N * m }
102
+ style: { height: P * h }
85
103
  }),
86
- I.map((t, r) => {
87
- let i = N + r;
88
- return /* @__PURE__ */ l("tr", {
89
- "aria-rowindex": i + 1,
90
- className: e(n.tr, y && n.clickable),
91
- style: { height: m },
92
- tabIndex: y ? 0 : void 0,
93
- onClick: y ? () => y(t, i) : void 0,
94
- onKeyDown: y ? (e) => {
95
- (e.key === "Enter" || e.key === " ") && (e.preventDefault(), y(t, i));
96
- } : void 0,
97
- children: p.map((r) => /* @__PURE__ */ l("td", {
98
- className: e(n.td, d(r.align)),
99
- style: { width: r.width },
100
- children: r.render ? r.render(t, i) : t[r.key] ?? null
101
- }, String(r.key)))
102
- }, _ ? _(t, i) : i);
104
+ L.map((e, t) => {
105
+ let n = P + t;
106
+ return /* @__PURE__ */ u(m, {
107
+ row: e,
108
+ index: n,
109
+ rowHeight: h,
110
+ columns: p,
111
+ onRowClick: b
112
+ }, v ? v(e, n) : n);
103
113
  }),
104
- F < M.length && /* @__PURE__ */ l("tr", {
114
+ I < N.length && /* @__PURE__ */ u("tr", {
105
115
  "aria-hidden": !0,
106
- style: { height: (M.length - F) * m }
116
+ style: { height: (N.length - I) * h }
107
117
  })
108
118
  ] }) })
109
119
  ]
@@ -111,6 +121,6 @@ function f({ data: f, columns: p, rowHeight: m, height: h, overscan: g = 4, rowK
111
121
  });
112
122
  }
113
123
  //#endregion
114
- export { f as VirtualTable };
124
+ export { h as VirtualTable };
115
125
 
116
126
  //# sourceMappingURL=VirtualTable.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VirtualTable.js","names":[],"sources":["../../../src/components/VirtualTable/VirtualTable.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count — windowing needs its own measurements\n * (rowHeight, height, overscan, scrollToIndex) on top of everything a table already\n * takes (data, columns, rowKey, initialSort, onRowClick, emptyMessage, caption). The\n * caption is not optional chrome — a virtualised grid without one is unreadable to a\n * screen reader.\n */\nimport {\n type HTMLAttributes,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\nimport { compareValues } from \"@/utils/compare-values\";\n\nimport type { TableAlign } from \"../Table\";\nimport styles from \"./VirtualTable.module.css\";\n\nexport type VirtualTableSortDirection = \"asc\" | \"desc\";\n\nexport interface VirtualTableSort<T> {\n key: keyof T;\n direction: VirtualTableSortDirection;\n}\n\nexport interface VirtualTableColumn<T> {\n /** Property of the row this column reads from. Doubles as the cell key. */\n key: keyof T;\n /** Column heading. */\n header: ReactNode;\n /** Custom cell renderer. Defaults to `row[key]`. */\n render?: (row: T, index: number) => ReactNode;\n /** Enable click-to-sort on this column's header. */\n sortable?: boolean;\n /** Text alignment. */\n align?: TableAlign;\n /**\n * Column width. Recommended for every column: virtualized rows enter and\n * leave the DOM as you scroll, so letting the browser auto-size columns from\n * whatever is currently rendered makes them jump mid-scroll.\n */\n width?: string | number;\n}\n\nexport interface VirtualTableProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** Full dataset. Every row is accounted for; only the visible ones render. */\n data: T[];\n /** Column definitions. */\n columns: VirtualTableColumn<T>[];\n /**\n * Row height in px. Must be uniform and must match what the CSS produces,\n * because it is what maps scroll offset to row index.\n */\n rowHeight: number;\n /** Height of the scroll viewport — a number of px or any CSS length. */\n height: number | string;\n /** Rows rendered above and below the viewport. Default `4`. */\n overscan?: number;\n /** Stable key extractor. Defaults to the row's index in `data`. */\n rowKey?: (row: T, index: number) => string | number;\n /** Sort applied before any header interaction. */\n initialSort?: VirtualTableSort<T>;\n /** Called when a row is activated by click, `Enter` or `Space`. */\n onRowClick?: (row: T, index: number) => void;\n /** Content shown when `data` is empty. */\n emptyMessage?: ReactNode;\n /** Accessible name for the table. Rendered as a visually hidden `<caption>`. */\n caption?: ReactNode;\n /** Scroll this row into view whenever it changes. */\n scrollToIndex?: number;\n}\n\n/** Resolve a column's alignment to its CSS module class. */\nfunction alignClass(align: TableAlign | undefined): string | undefined {\n if (align === \"right\") return styles.alignRight;\n if (align === \"center\") return styles.alignCenter;\n return undefined;\n}\n\n/**\n * A table that stays responsive at 10k+ rows by rendering only the visible window.\n *\n * `Table` renders every row it is given and `DataTable` paginates to keep that\n * count small; neither has an answer for \"show me all 40 000 rows in one\n * scrollable grid\". This does, at the cost of one constraint: **`rowHeight` must\n * be uniform**, since mapping a scroll offset to a row index is what makes the\n * window computable without measuring anything.\n *\n * It stays a real `<table>`. The window is produced by two spacer rows — one\n * above the visible slice, one below — instead of absolutely positioning rows.\n * That is deliberate: `position: absolute` on `<tr>` collapses table layout, so\n * every column width would have to be computed by hand, and the element would\n * stop being a table for assistive technology. With spacer rows the browser keeps\n * doing column layout and screen readers keep announcing a grid.\n *\n * Because only a slice is in the DOM, `aria-rowcount` on the table and\n * `aria-rowindex` on each row carry the real numbers — without them a screen\n * reader announces \"row 3 of 20\" while the user is on row 5003 of 40 000.\n *\n * @example\n * <VirtualTable\n * data={rows}\n * columns={[\n * { key: \"id\", header: \"#\", width: 80, sortable: true },\n * { key: \"name\", header: \"Nome\", width: 240, sortable: true },\n * { key: \"total\", header: \"Total\", align: \"right\", width: 120, sortable: true },\n * ]}\n * rowHeight={40}\n * height={480}\n * rowKey={(row) => row.id}\n * />\n */\nexport function VirtualTable<T>({\n data,\n columns,\n rowHeight,\n height,\n overscan = 4,\n rowKey,\n initialSort,\n onRowClick,\n emptyMessage = \"Nenhum registro encontrado.\",\n caption,\n scrollToIndex,\n className,\n ...rest\n}: VirtualTableProps<T>) {\n const scrollRef = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState<number>(0);\n const [viewport, setViewport] = useState<number>(0);\n const [sort, setSort] = useState<VirtualTableSort<T> | null>(initialSort ?? null);\n\n useEffect(() => {\n const element = scrollRef.current;\n if (!element) return;\n setViewport(element.clientHeight);\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => setViewport(element.clientHeight));\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n const element = scrollRef.current;\n if (!element || scrollToIndex == null) return;\n element.scrollTop = Math.max(0, Math.min(scrollToIndex, data.length - 1)) * rowHeight;\n }, [scrollToIndex, rowHeight, data.length]);\n\n const sorted = useMemo<T[]>(() => {\n if (!sort) return data;\n const factor = sort.direction === \"asc\" ? 1 : -1;\n return [...data].sort((a, b) => compareValues(a[sort.key], b[sort.key]) * factor);\n }, [data, sort]);\n\n const start = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);\n const windowSize = Math.ceil(viewport / rowHeight) + overscan * 2;\n const end = Math.min(sorted.length, start + windowSize);\n const slice = sorted.slice(start, end);\n\n /**\n * Advance a column through asc → desc → unsorted, and jump back to the top.\n *\n * The scroll reset happens here rather than in an effect keyed on the sort\n * state for two reasons: this is the actual event that invalidates the offset\n * (keeping it would leave the user at the same pixel of a different dataset,\n * which reads as the table having jumped somewhere random), and an effect would\n * also fire on mount — clobbering an initial `scrollToIndex`.\n */\n const toggleSort = useCallback((key: keyof T): void => {\n setSort((current) => {\n if (!current || current.key !== key) return { key, direction: \"asc\" };\n if (current.direction === \"asc\") return { key, direction: \"desc\" };\n return null;\n });\n const element = scrollRef.current;\n if (element) element.scrollTop = 0;\n setScrollTop(0);\n }, []);\n\n return (\n <div\n ref={scrollRef}\n className={cn(styles.scroll, className)}\n style={{ height }}\n onScroll={(event) => setScrollTop(event.currentTarget.scrollTop)}\n {...rest}\n >\n <table className={styles.table} aria-rowcount={sorted.length}>\n {caption ? <caption className={styles.caption}>{caption}</caption> : null}\n <thead className={styles.head}>\n <tr>\n {columns.map((column) => {\n const isSorted = sort?.key === column.key;\n return (\n <th\n key={String(column.key)}\n scope=\"col\"\n className={cn(styles.th, alignClass(column.align))}\n style={{ width: column.width }}\n aria-sort={\n isSorted\n ? sort?.direction === \"asc\"\n ? \"ascending\"\n : \"descending\"\n : column.sortable\n ? \"none\"\n : undefined\n }\n >\n {column.sortable ? (\n <button\n type=\"button\"\n className={styles.sortButton}\n onClick={() => toggleSort(column.key)}\n >\n {column.header}\n <span className={styles.sortIndicator} aria-hidden>\n {isSorted\n ? sort?.direction === \"asc\"\n ? \"▲\"\n : \"▼\"\n : \"↕\"}\n </span>\n </button>\n ) : (\n column.header\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {sorted.length === 0 ? (\n <tr>\n <td className={styles.emptyRow} colSpan={columns.length}>\n {emptyMessage}\n </td>\n </tr>\n ) : (\n <>\n {start > 0 && <tr aria-hidden style={{ height: start * rowHeight }} />}\n {slice.map((row, offset) => {\n const index = start + offset;\n return (\n <tr\n key={rowKey ? rowKey(row, index) : index}\n aria-rowindex={index + 1}\n className={cn(styles.tr, onRowClick && styles.clickable)}\n style={{ height: rowHeight }}\n tabIndex={onRowClick ? 0 : undefined}\n onClick={\n onRowClick ? () => onRowClick(row, index) : undefined\n }\n onKeyDown={\n onRowClick\n ? (event) => {\n if (\n event.key === \"Enter\" ||\n event.key === \" \"\n ) {\n event.preventDefault();\n onRowClick(row, index);\n }\n }\n : undefined\n }\n >\n {columns.map((column) => (\n <td\n key={String(column.key)}\n className={cn(styles.td, alignClass(column.align))}\n style={{ width: column.width }}\n >\n {column.render\n ? column.render(row, index)\n : ((row[column.key] as ReactNode) ?? null)}\n </td>\n ))}\n </tr>\n );\n })}\n {end < sorted.length && (\n <tr\n aria-hidden\n style={{ height: (sorted.length - end) * rowHeight }}\n />\n )}\n </>\n )}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"VirtualTable.js","names":[],"sources":["../../../src/components/VirtualTable/VirtualTable.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count — windowing needs its own measurements\n * (rowHeight, height, overscan, scrollToIndex) on top of everything a table already\n * takes (data, columns, rowKey, initialSort, onRowClick, emptyMessage, caption). The\n * caption is not optional chrome — a virtualised grid without one is unreadable to a\n * screen reader.\n */\nimport {\n type HTMLAttributes,\n type ReactNode,\n memo,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\nimport { compareValues } from \"@/utils/compare-values\";\n\nimport type { TableAlign } from \"../Table\";\nimport styles from \"./VirtualTable.module.css\";\n\nexport type VirtualTableSortDirection = \"asc\" | \"desc\";\n\nexport interface VirtualTableSort<T> {\n key: keyof T;\n direction: VirtualTableSortDirection;\n}\n\nexport interface VirtualTableColumn<T> {\n /** Property of the row this column reads from. Doubles as the cell key. */\n key: keyof T;\n /** Column heading. */\n header: ReactNode;\n /** Custom cell renderer. Defaults to `row[key]`. */\n render?: (row: T, index: number) => ReactNode;\n /** Enable click-to-sort on this column's header. */\n sortable?: boolean;\n /** Text alignment. */\n align?: TableAlign;\n /**\n * Column width. Recommended for every column: virtualized rows enter and\n * leave the DOM as you scroll, so letting the browser auto-size columns from\n * whatever is currently rendered makes them jump mid-scroll.\n */\n width?: string | number;\n}\n\nexport interface VirtualTableProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** Full dataset. Every row is accounted for; only the visible ones render. */\n data: T[];\n /** Column definitions. */\n columns: VirtualTableColumn<T>[];\n /**\n * Row height in px. Must be uniform and must match what the CSS produces,\n * because it is what maps scroll offset to row index.\n */\n rowHeight: number;\n /** Height of the scroll viewport — a number of px or any CSS length. */\n height: number | string;\n /** Rows rendered above and below the viewport. Default `4`. */\n overscan?: number;\n /** Stable key extractor. Defaults to the row's index in `data`. */\n rowKey?: (row: T, index: number) => string | number;\n /** Sort applied before any header interaction. */\n initialSort?: VirtualTableSort<T>;\n /** Called when a row is activated by click, `Enter` or `Space`. */\n onRowClick?: (row: T, index: number) => void;\n /** Content shown when `data` is empty. */\n emptyMessage?: ReactNode;\n /** Accessible name for the table. Rendered as a visually hidden `<caption>`. */\n caption?: ReactNode;\n /** Scroll this row into view whenever it changes. */\n scrollToIndex?: number;\n}\n\n/** Resolve a column's alignment to its CSS module class. */\nfunction alignClass(align: TableAlign | undefined): string | undefined {\n if (align === \"right\") return styles.alignRight;\n if (align === \"center\") return styles.alignCenter;\n return undefined;\n}\n\ninterface VirtualTableRowProps<T> {\n row: T;\n index: number;\n rowHeight: number;\n columns: VirtualTableColumn<T>[];\n onRowClick: ((row: T, index: number) => void) | undefined;\n}\n\n/**\n * One windowed table row, rendered on its own so React can skip it.\n *\n * Scrolling changes state that lives inside `VirtualTable`, so without this\n * boundary every scroll event re-rendered every visible row and every cell in\n * them — including whatever `column.render` builds — rather than the one row\n * that entered the window.\n *\n * `columns` and `onRowClick` take part in the comparison because a cell renderer\n * closes over the app's state: leaving them out would freeze a row showing a\n * stale cell. An app that keeps its `columns` array stable (a module constant, or\n * `useMemo`) therefore gets the skip, and one that rebuilds it every render gets\n * exactly today's behaviour.\n *\n * @param props - The row, its position and the column contract.\n * @returns The table row element.\n */\nfunction VirtualTableRowImpl<T>({\n row,\n index,\n rowHeight,\n columns,\n onRowClick,\n}: VirtualTableRowProps<T>) {\n return (\n <tr\n aria-rowindex={index + 1}\n className={cn(styles.tr, onRowClick && styles.clickable)}\n style={{ height: rowHeight }}\n tabIndex={onRowClick ? 0 : undefined}\n onClick={onRowClick ? () => onRowClick(row, index) : undefined}\n onKeyDown={\n onRowClick\n ? (event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onRowClick(row, index);\n }\n }\n : undefined\n }\n >\n {columns.map((column) => (\n <td\n key={String(column.key)}\n className={cn(styles.td, alignClass(column.align))}\n style={{ width: column.width }}\n >\n {column.render\n ? column.render(row, index)\n : ((row[column.key] as ReactNode) ?? null)}\n </td>\n ))}\n </tr>\n );\n}\n\n/**\n * `memo` erases the generic, so the memoised component is re-typed as the\n * function it wraps. The runtime value is unchanged; only the signature is\n * restored.\n */\nconst VirtualTableRow = memo(VirtualTableRowImpl) as typeof VirtualTableRowImpl;\n\n/**\n * A table that stays responsive at 10k+ rows by rendering only the visible window.\n *\n * `Table` renders every row it is given and `DataTable` paginates to keep that\n * count small; neither has an answer for \"show me all 40 000 rows in one\n * scrollable grid\". This does, at the cost of one constraint: **`rowHeight` must\n * be uniform**, since mapping a scroll offset to a row index is what makes the\n * window computable without measuring anything.\n *\n * It stays a real `<table>`. The window is produced by two spacer rows — one\n * above the visible slice, one below — instead of absolutely positioning rows.\n * That is deliberate: `position: absolute` on `<tr>` collapses table layout, so\n * every column width would have to be computed by hand, and the element would\n * stop being a table for assistive technology. With spacer rows the browser keeps\n * doing column layout and screen readers keep announcing a grid.\n *\n * Because only a slice is in the DOM, `aria-rowcount` on the table and\n * `aria-rowindex` on each row carry the real numbers — without them a screen\n * reader announces \"row 3 of 20\" while the user is on row 5003 of 40 000.\n *\n * @example\n * <VirtualTable\n * data={rows}\n * columns={[\n * { key: \"id\", header: \"#\", width: 80, sortable: true },\n * { key: \"name\", header: \"Nome\", width: 240, sortable: true },\n * { key: \"total\", header: \"Total\", align: \"right\", width: 120, sortable: true },\n * ]}\n * rowHeight={40}\n * height={480}\n * rowKey={(row) => row.id}\n * />\n */\nexport function VirtualTable<T>({\n data,\n columns,\n rowHeight,\n height,\n overscan = 4,\n rowKey,\n initialSort,\n onRowClick,\n emptyMessage = \"Nenhum registro encontrado.\",\n caption,\n scrollToIndex,\n className,\n ...rest\n}: VirtualTableProps<T>) {\n const scrollRef = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState<number>(0);\n const [viewport, setViewport] = useState<number>(0);\n const [sort, setSort] = useState<VirtualTableSort<T> | null>(initialSort ?? null);\n\n useEffect(() => {\n const element = scrollRef.current;\n if (!element) return;\n setViewport(element.clientHeight);\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => setViewport(element.clientHeight));\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n const element = scrollRef.current;\n if (!element || scrollToIndex == null) return;\n element.scrollTop = Math.max(0, Math.min(scrollToIndex, data.length - 1)) * rowHeight;\n }, [scrollToIndex, rowHeight, data.length]);\n\n const sorted = useMemo<T[]>(() => {\n if (!sort) return data;\n const factor = sort.direction === \"asc\" ? 1 : -1;\n return [...data].sort((a, b) => compareValues(a[sort.key], b[sort.key]) * factor);\n }, [data, sort]);\n\n const start = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);\n const windowSize = Math.ceil(viewport / rowHeight) + overscan * 2;\n const end = Math.min(sorted.length, start + windowSize);\n const slice = sorted.slice(start, end);\n\n /**\n * Advance a column through asc → desc → unsorted, and jump back to the top.\n *\n * The scroll reset happens here rather than in an effect keyed on the sort\n * state for two reasons: this is the actual event that invalidates the offset\n * (keeping it would leave the user at the same pixel of a different dataset,\n * which reads as the table having jumped somewhere random), and an effect would\n * also fire on mount — clobbering an initial `scrollToIndex`.\n */\n const toggleSort = useCallback((key: keyof T): void => {\n setSort((current) => {\n if (!current || current.key !== key) return { key, direction: \"asc\" };\n if (current.direction === \"asc\") return { key, direction: \"desc\" };\n return null;\n });\n const element = scrollRef.current;\n if (element) element.scrollTop = 0;\n setScrollTop(0);\n }, []);\n\n return (\n <div\n ref={scrollRef}\n className={cn(styles.scroll, className)}\n style={{ height }}\n onScroll={(event) => setScrollTop(event.currentTarget.scrollTop)}\n {...rest}\n >\n <table className={styles.table} aria-rowcount={sorted.length}>\n {caption ? <caption className={styles.caption}>{caption}</caption> : null}\n <thead className={styles.head}>\n <tr>\n {columns.map((column) => {\n const isSorted = sort?.key === column.key;\n return (\n <th\n key={String(column.key)}\n scope=\"col\"\n className={cn(styles.th, alignClass(column.align))}\n style={{ width: column.width }}\n aria-sort={\n isSorted\n ? sort?.direction === \"asc\"\n ? \"ascending\"\n : \"descending\"\n : column.sortable\n ? \"none\"\n : undefined\n }\n >\n {column.sortable ? (\n <button\n type=\"button\"\n className={styles.sortButton}\n onClick={() => toggleSort(column.key)}\n >\n {column.header}\n <span className={styles.sortIndicator} aria-hidden>\n {isSorted\n ? sort?.direction === \"asc\"\n ? \"▲\"\n : \"▼\"\n : \"↕\"}\n </span>\n </button>\n ) : (\n column.header\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {sorted.length === 0 ? (\n <tr>\n <td className={styles.emptyRow} colSpan={columns.length}>\n {emptyMessage}\n </td>\n </tr>\n ) : (\n <>\n {start > 0 && <tr aria-hidden style={{ height: start * rowHeight }} />}\n {slice.map((row, offset) => {\n const index = start + offset;\n return (\n <VirtualTableRow\n key={rowKey ? rowKey(row, index) : index}\n row={row}\n index={index}\n rowHeight={rowHeight}\n columns={columns}\n onRowClick={onRowClick}\n />\n );\n })}\n {end < sorted.length && (\n <tr\n aria-hidden\n style={{ height: (sorted.length - end) * rowHeight }}\n />\n )}\n </>\n )}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- let e=require("react"),t=require("react/jsx-runtime"),n=require("react-hook-form");function r({name:r,label:i,helperText:a,required:o,control:s,children:c}){let l=(0,n.useFormContext)(),u=s??l?.control;if(!u)throw Error("FormField requires either a `control` prop or a <FormProvider> in the tree.");return(0,t.jsx)(n.Controller,{name:r,control:u,render:({field:t,fieldState:n})=>{if(!(0,e.isValidElement)(c))return c;let r=n.error?.message;return(0,e.cloneElement)(c,{name:t.name,value:t.value,onChange:t.onChange,onBlur:t.onBlur,ref:t.ref,label:i,helperText:r?void 0:a,error:r,required:o,"aria-invalid":!!r})}})}exports.FormField=r;
1
+ const e=require("../utils/duplicate-instance.cjs");let t=require("react"),n=require("react/jsx-runtime"),r=require("react-hook-form");var i="FormField found no form to bind to. Either pass a `control` prop, or mount a <FormProvider> above it. If a <FormProvider> IS mounted above it, the app and the SDK are resolving two copies of react-hook-form: the provider publishes on one copy's context and this field reads the other's. "+e.DUPLICATE_COPY_REMEDY;function a({name:e,label:a,helperText:o,required:s,control:c,children:l}){let u=(0,r.useFormContext)(),d=c??u?.control;if(!d)throw Error(i);return(0,n.jsx)(r.Controller,{name:e,control:d,render:({field:e,fieldState:n})=>{if(!(0,t.isValidElement)(l))return l;let r=n.error?.message;return(0,t.cloneElement)(l,{name:e.name,value:e.value,onChange:e.onChange,onBlur:e.onBlur,ref:e.ref,label:a,helperText:r?void 0:o,error:r,required:s,"aria-invalid":!!r})}})}exports.FormField=a;
2
2
  //# sourceMappingURL=FormField.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"FormField.cjs","names":[],"sources":["../../src/forms/FormField.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — FormFieldChildProps is not a component's props — it\n * is the contract handed to whatever control the field wraps, and it is exactly what\n * react-hook-form's register returns (name, value, onChange, onBlur, ref) plus what\n * the field adds around it (error, label, helperText, required, id). Trimming it\n * breaks the wiring it exists to describe.\n */\nimport { cloneElement, isValidElement } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport {\n Controller,\n useFormContext,\n type Control,\n type ControllerRenderProps,\n type FieldPath,\n type FieldValues,\n} from \"react-hook-form\";\n\nexport interface FormFieldChildProps {\n name: string;\n value: unknown;\n onChange: (...args: unknown[]) => void;\n onBlur: () => void;\n ref: ControllerRenderProps[\"ref\"];\n error?: string;\n \"aria-invalid\"?: boolean;\n \"aria-describedby\"?: string;\n label?: ReactNode;\n helperText?: ReactNode;\n required?: boolean;\n id?: string;\n}\n\nexport interface FormFieldProps<\n TValues extends FieldValues = FieldValues,\n TName extends FieldPath<TValues> = FieldPath<TValues>,\n> {\n /** Field name (dot path supported, e.g. `\"address.city\"`). */\n name: TName;\n /** Field label rendered by the wrapped control. */\n label?: ReactNode;\n /** Helper text rendered by the wrapped control when there is no error. */\n helperText?: ReactNode;\n /** When `true`, marks the control as required (visual hint + native attribute). */\n required?: boolean;\n /**\n * Explicit `control` from `useForm()` / `useZodForm()`. Optional when a\n * `FormProvider` is in the tree.\n */\n control?: Control<TValues>;\n /**\n * The control to render. Receives `{ value, onChange, onBlur, ref, error, ... }`\n * via `cloneElement`. Pass `<Input />`, `<Select />`, masked inputs, etc.\n */\n children: ReactElement;\n}\n\n/**\n * Glue between `react-hook-form` `Controller` and the SDK's controlled\n * components. Wraps any control that accepts `{ value, onChange, label,\n * error }` and routes RHF state into it — eliminating the per-field\n * `<Controller render={...} />` boilerplate.\n *\n * @example\n * const form = useZodForm(schema);\n * <FormProvider {...form}>\n * <Form>\n * <FormField name=\"email\" label=\"Email\" required>\n * <Input type=\"email\" />\n * </FormField>\n * <FormField name=\"cep\" label=\"CEP\">\n * <CEPInput />\n * </FormField>\n * </Form>\n * </FormProvider>;\n */\nexport function FormField<\n TValues extends FieldValues = FieldValues,\n TName extends FieldPath<TValues> = FieldPath<TValues>,\n>({ name, label, helperText, required, control, children }: FormFieldProps<TValues, TName>) {\n const context = useFormContext<TValues>();\n const resolvedControl = control ?? context?.control;\n if (!resolvedControl) {\n throw new Error(\n \"FormField requires either a `control` prop or a <FormProvider> in the tree.\",\n );\n }\n\n return (\n <Controller\n name={name}\n control={resolvedControl}\n render={({ field, fieldState }) => {\n if (!isValidElement(children)) return children;\n const errorMessage = fieldState.error?.message;\n return cloneElement(children as ReactElement<FormFieldChildProps>, {\n name: field.name,\n value: field.value,\n onChange: field.onChange,\n onBlur: field.onBlur,\n ref: field.ref,\n label,\n helperText: errorMessage ? undefined : helperText,\n error: errorMessage,\n required,\n \"aria-invalid\": !!errorMessage,\n });\n }}\n />\n );\n}\n"],"mappings":"mFA4EA,SAAgB,EAGd,CAAE,OAAM,QAAO,aAAY,WAAU,UAAS,YAA4C,CACxF,IAAM,GAAA,EAAU,EAAA,eAAA,CAAwB,EAClC,EAAkB,GAAW,GAAS,QAC5C,GAAI,CAAC,EACD,MAAU,MACN,6EACJ,EAGJ,OACI,EAAA,EAAA,IAAA,CAAC,EAAA,WAAD,CACU,OACN,QAAS,EACT,QAAS,CAAE,QAAO,gBAAiB,CAC/B,GAAI,EAAA,EAAC,EAAA,eAAA,CAAe,CAAQ,EAAG,OAAO,EACtC,IAAM,EAAe,EAAW,OAAO,QACvC,OAAA,EAAO,EAAA,aAAA,CAAa,EAA+C,CAC/D,KAAM,EAAM,KACZ,MAAO,EAAM,MACb,SAAU,EAAM,SAChB,OAAQ,EAAM,OACd,IAAK,EAAM,IACX,QACA,WAAY,EAAe,IAAA,GAAY,EACvC,MAAO,EACP,WACA,eAAgB,CAAC,CAAC,CACtB,CAAC,CACL,CACH,CAAA,CAET"}
1
+ {"version":3,"file":"FormField.cjs","names":[],"sources":["../../src/forms/FormField.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — FormFieldChildProps is not a component's props — it\n * is the contract handed to whatever control the field wraps, and it is exactly what\n * react-hook-form's register returns (name, value, onChange, onBlur, ref) plus what\n * the field adds around it (error, label, helperText, required, id). Trimming it\n * breaks the wiring it exists to describe.\n */\nimport { cloneElement, isValidElement } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport {\n Controller,\n useFormContext,\n type Control,\n type ControllerRenderProps,\n type FieldPath,\n type FieldValues,\n} from \"react-hook-form\";\n\nimport { DUPLICATE_COPY_REMEDY } from \"../utils/duplicate-instance\";\n\nexport interface FormFieldChildProps {\n name: string;\n value: unknown;\n onChange: (...args: unknown[]) => void;\n onBlur: () => void;\n ref: ControllerRenderProps[\"ref\"];\n error?: string;\n \"aria-invalid\"?: boolean;\n \"aria-describedby\"?: string;\n label?: ReactNode;\n helperText?: ReactNode;\n required?: boolean;\n id?: string;\n}\n\nexport interface FormFieldProps<\n TValues extends FieldValues = FieldValues,\n TName extends FieldPath<TValues> = FieldPath<TValues>,\n> {\n /** Field name (dot path supported, e.g. `\"address.city\"`). */\n name: TName;\n /** Field label rendered by the wrapped control. */\n label?: ReactNode;\n /** Helper text rendered by the wrapped control when there is no error. */\n helperText?: ReactNode;\n /** When `true`, marks the control as required (visual hint + native attribute). */\n required?: boolean;\n /**\n * Explicit `control` from `useForm()` / `useZodForm()`. Optional when a\n * `FormProvider` is in the tree.\n */\n control?: Control<TValues>;\n /**\n * The control to render. Receives `{ value, onChange, onBlur, ref, error, ... }`\n * via `cloneElement`. Pass `<Input />`, `<Select />`, masked inputs, etc.\n */\n children: ReactElement;\n}\n\n/**\n * Glue between `react-hook-form` `Controller` and the SDK's controlled\n * components. Wraps any control that accepts `{ value, onChange, label,\n * error }` and routes RHF state into it — eliminating the per-field\n * `<Controller render={...} />` boilerplate.\n *\n * @example\n * const form = useZodForm(schema);\n * <FormProvider {...form}>\n * <Form>\n * <FormField name=\"email\" label=\"Email\" required>\n * <Input type=\"email\" />\n * </FormField>\n * <FormField name=\"cep\" label=\"CEP\">\n * <CEPInput />\n * </FormField>\n * </Form>\n * </FormProvider>;\n */\n/**\n * What is thrown when no `control` can be resolved.\n *\n * It names **two** causes, because the throw cannot tell them apart and the\n * second one is the expensive one. The obvious reading — no provider, no prop —\n * is usually right. But the identical throw happens with a `<FormProvider>`\n * mounted directly above, when the app and the SDK resolve two different copies\n * of `react-hook-form`: the provider publishes on the app copy's context and\n * `useFormContext` here reads the SDK copy's, which is empty. Someone looking at\n * a provider they can see, being told it is missing, does not go looking at\n * `node_modules` — so the message has to send them there.\n */\nconst NO_CONTROL_MESSAGE =\n \"FormField found no form to bind to. Either pass a `control` prop, or mount a \" +\n \"<FormProvider> above it. If a <FormProvider> IS mounted above it, the app and the \" +\n \"SDK are resolving two copies of react-hook-form: the provider publishes on one \" +\n \"copy's context and this field reads the other's. \" +\n DUPLICATE_COPY_REMEDY;\n\nexport function FormField<\n TValues extends FieldValues = FieldValues,\n TName extends FieldPath<TValues> = FieldPath<TValues>,\n>({ name, label, helperText, required, control, children }: FormFieldProps<TValues, TName>) {\n const context = useFormContext<TValues>();\n const resolvedControl = control ?? context?.control;\n if (!resolvedControl) {\n throw new Error(NO_CONTROL_MESSAGE);\n }\n\n return (\n <Controller\n name={name}\n control={resolvedControl}\n render={({ field, fieldState }) => {\n if (!isValidElement(children)) return children;\n const errorMessage = fieldState.error?.message;\n return cloneElement(children as ReactElement<FormFieldChildProps>, {\n name: field.name,\n value: field.value,\n onChange: field.onChange,\n onBlur: field.onBlur,\n ref: field.ref,\n label,\n helperText: errorMessage ? undefined : helperText,\n error: errorMessage,\n required,\n \"aria-invalid\": !!errorMessage,\n });\n }}\n />\n );\n}\n"],"mappings":"sIA0FA,IAAM,EACF,kSAIA,EAAA,sBAEJ,SAAgB,EAGd,CAAE,OAAM,QAAO,aAAY,WAAU,UAAS,YAA4C,CACxF,IAAM,GAAA,EAAU,EAAA,eAAA,CAAwB,EAClC,EAAkB,GAAW,GAAS,QAC5C,GAAI,CAAC,EACD,MAAU,MAAM,CAAkB,EAGtC,OACI,EAAA,EAAA,IAAA,CAAC,EAAA,WAAD,CACU,OACN,QAAS,EACT,QAAS,CAAE,QAAO,gBAAiB,CAC/B,GAAI,EAAA,EAAC,EAAA,eAAA,CAAe,CAAQ,EAAG,OAAO,EACtC,IAAM,EAAe,EAAW,OAAO,QACvC,OAAA,EAAO,EAAA,aAAA,CAAa,EAA+C,CAC/D,KAAM,EAAM,KACZ,MAAO,EAAM,MACb,SAAU,EAAM,SAChB,OAAQ,EAAM,OACd,IAAK,EAAM,IACX,QACA,WAAY,EAAe,IAAA,GAAY,EACvC,MAAO,EACP,WACA,eAAgB,CAAC,CAAC,CACtB,CAAC,CACL,CACH,CAAA,CAET"}
@@ -1,32 +1,34 @@
1
- import { cloneElement as e, isValidElement as t } from "react";
2
- import { jsx as n } from "react/jsx-runtime";
3
- import { Controller as r, useFormContext as i } from "react-hook-form";
1
+ import { DUPLICATE_COPY_REMEDY as e } from "../utils/duplicate-instance.js";
2
+ import { cloneElement as t, isValidElement as n } from "react";
3
+ import { jsx as r } from "react/jsx-runtime";
4
+ import { Controller as i, useFormContext as a } from "react-hook-form";
4
5
  //#region src/forms/FormField.tsx
5
- function a({ name: a, label: o, helperText: s, required: c, control: l, children: u }) {
6
- let d = i(), f = l ?? d?.control;
7
- if (!f) throw Error("FormField requires either a `control` prop or a <FormProvider> in the tree.");
8
- return /* @__PURE__ */ n(r, {
9
- name: a,
10
- control: f,
11
- render: ({ field: n, fieldState: r }) => {
12
- if (!t(u)) return u;
6
+ var o = "FormField found no form to bind to. Either pass a `control` prop, or mount a <FormProvider> above it. If a <FormProvider> IS mounted above it, the app and the SDK are resolving two copies of react-hook-form: the provider publishes on one copy's context and this field reads the other's. " + e;
7
+ function s({ name: e, label: s, helperText: c, required: l, control: u, children: d }) {
8
+ let f = a(), p = u ?? f?.control;
9
+ if (!p) throw Error(o);
10
+ return /* @__PURE__ */ r(i, {
11
+ name: e,
12
+ control: p,
13
+ render: ({ field: e, fieldState: r }) => {
14
+ if (!n(d)) return d;
13
15
  let i = r.error?.message;
14
- return e(u, {
15
- name: n.name,
16
- value: n.value,
17
- onChange: n.onChange,
18
- onBlur: n.onBlur,
19
- ref: n.ref,
20
- label: o,
21
- helperText: i ? void 0 : s,
16
+ return t(d, {
17
+ name: e.name,
18
+ value: e.value,
19
+ onChange: e.onChange,
20
+ onBlur: e.onBlur,
21
+ ref: e.ref,
22
+ label: s,
23
+ helperText: i ? void 0 : c,
22
24
  error: i,
23
- required: c,
25
+ required: l,
24
26
  "aria-invalid": !!i
25
27
  });
26
28
  }
27
29
  });
28
30
  }
29
31
  //#endregion
30
- export { a as FormField };
32
+ export { s as FormField };
31
33
 
32
34
  //# sourceMappingURL=FormField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FormField.js","names":[],"sources":["../../src/forms/FormField.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — FormFieldChildProps is not a component's props — it\n * is the contract handed to whatever control the field wraps, and it is exactly what\n * react-hook-form's register returns (name, value, onChange, onBlur, ref) plus what\n * the field adds around it (error, label, helperText, required, id). Trimming it\n * breaks the wiring it exists to describe.\n */\nimport { cloneElement, isValidElement } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport {\n Controller,\n useFormContext,\n type Control,\n type ControllerRenderProps,\n type FieldPath,\n type FieldValues,\n} from \"react-hook-form\";\n\nexport interface FormFieldChildProps {\n name: string;\n value: unknown;\n onChange: (...args: unknown[]) => void;\n onBlur: () => void;\n ref: ControllerRenderProps[\"ref\"];\n error?: string;\n \"aria-invalid\"?: boolean;\n \"aria-describedby\"?: string;\n label?: ReactNode;\n helperText?: ReactNode;\n required?: boolean;\n id?: string;\n}\n\nexport interface FormFieldProps<\n TValues extends FieldValues = FieldValues,\n TName extends FieldPath<TValues> = FieldPath<TValues>,\n> {\n /** Field name (dot path supported, e.g. `\"address.city\"`). */\n name: TName;\n /** Field label rendered by the wrapped control. */\n label?: ReactNode;\n /** Helper text rendered by the wrapped control when there is no error. */\n helperText?: ReactNode;\n /** When `true`, marks the control as required (visual hint + native attribute). */\n required?: boolean;\n /**\n * Explicit `control` from `useForm()` / `useZodForm()`. Optional when a\n * `FormProvider` is in the tree.\n */\n control?: Control<TValues>;\n /**\n * The control to render. Receives `{ value, onChange, onBlur, ref, error, ... }`\n * via `cloneElement`. Pass `<Input />`, `<Select />`, masked inputs, etc.\n */\n children: ReactElement;\n}\n\n/**\n * Glue between `react-hook-form` `Controller` and the SDK's controlled\n * components. Wraps any control that accepts `{ value, onChange, label,\n * error }` and routes RHF state into it — eliminating the per-field\n * `<Controller render={...} />` boilerplate.\n *\n * @example\n * const form = useZodForm(schema);\n * <FormProvider {...form}>\n * <Form>\n * <FormField name=\"email\" label=\"Email\" required>\n * <Input type=\"email\" />\n * </FormField>\n * <FormField name=\"cep\" label=\"CEP\">\n * <CEPInput />\n * </FormField>\n * </Form>\n * </FormProvider>;\n */\nexport function FormField<\n TValues extends FieldValues = FieldValues,\n TName extends FieldPath<TValues> = FieldPath<TValues>,\n>({ name, label, helperText, required, control, children }: FormFieldProps<TValues, TName>) {\n const context = useFormContext<TValues>();\n const resolvedControl = control ?? context?.control;\n if (!resolvedControl) {\n throw new Error(\n \"FormField requires either a `control` prop or a <FormProvider> in the tree.\",\n );\n }\n\n return (\n <Controller\n name={name}\n control={resolvedControl}\n render={({ field, fieldState }) => {\n if (!isValidElement(children)) return children;\n const errorMessage = fieldState.error?.message;\n return cloneElement(children as ReactElement<FormFieldChildProps>, {\n name: field.name,\n value: field.value,\n onChange: field.onChange,\n onBlur: field.onBlur,\n ref: field.ref,\n label,\n helperText: errorMessage ? undefined : helperText,\n error: errorMessage,\n required,\n \"aria-invalid\": !!errorMessage,\n });\n }}\n />\n );\n}\n"],"mappings":";;;;AA4EA,SAAgB,EAGd,EAAE,SAAM,UAAO,eAAY,aAAU,YAAS,eAA4C;CACxF,IAAM,IAAU,EAAwB,GAClC,IAAkB,KAAW,GAAS;CAC5C,IAAI,CAAC,GACD,MAAU,MACN,6EACJ;CAGJ,OACI,kBAAC,GAAD;EACU;EACN,SAAS;EACT,SAAS,EAAE,UAAO,oBAAiB;GAC/B,IAAI,CAAC,EAAe,CAAQ,GAAG,OAAO;GACtC,IAAM,IAAe,EAAW,OAAO;GACvC,OAAO,EAAa,GAA+C;IAC/D,MAAM,EAAM;IACZ,OAAO,EAAM;IACb,UAAU,EAAM;IAChB,QAAQ,EAAM;IACd,KAAK,EAAM;IACX;IACA,YAAY,IAAe,KAAA,IAAY;IACvC,OAAO;IACP;IACA,gBAAgB,CAAC,CAAC;GACtB,CAAC;EACL;CACH,CAAA;AAET"}
1
+ {"version":3,"file":"FormField.js","names":[],"sources":["../../src/forms/FormField.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — FormFieldChildProps is not a component's props — it\n * is the contract handed to whatever control the field wraps, and it is exactly what\n * react-hook-form's register returns (name, value, onChange, onBlur, ref) plus what\n * the field adds around it (error, label, helperText, required, id). Trimming it\n * breaks the wiring it exists to describe.\n */\nimport { cloneElement, isValidElement } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport {\n Controller,\n useFormContext,\n type Control,\n type ControllerRenderProps,\n type FieldPath,\n type FieldValues,\n} from \"react-hook-form\";\n\nimport { DUPLICATE_COPY_REMEDY } from \"../utils/duplicate-instance\";\n\nexport interface FormFieldChildProps {\n name: string;\n value: unknown;\n onChange: (...args: unknown[]) => void;\n onBlur: () => void;\n ref: ControllerRenderProps[\"ref\"];\n error?: string;\n \"aria-invalid\"?: boolean;\n \"aria-describedby\"?: string;\n label?: ReactNode;\n helperText?: ReactNode;\n required?: boolean;\n id?: string;\n}\n\nexport interface FormFieldProps<\n TValues extends FieldValues = FieldValues,\n TName extends FieldPath<TValues> = FieldPath<TValues>,\n> {\n /** Field name (dot path supported, e.g. `\"address.city\"`). */\n name: TName;\n /** Field label rendered by the wrapped control. */\n label?: ReactNode;\n /** Helper text rendered by the wrapped control when there is no error. */\n helperText?: ReactNode;\n /** When `true`, marks the control as required (visual hint + native attribute). */\n required?: boolean;\n /**\n * Explicit `control` from `useForm()` / `useZodForm()`. Optional when a\n * `FormProvider` is in the tree.\n */\n control?: Control<TValues>;\n /**\n * The control to render. Receives `{ value, onChange, onBlur, ref, error, ... }`\n * via `cloneElement`. Pass `<Input />`, `<Select />`, masked inputs, etc.\n */\n children: ReactElement;\n}\n\n/**\n * Glue between `react-hook-form` `Controller` and the SDK's controlled\n * components. Wraps any control that accepts `{ value, onChange, label,\n * error }` and routes RHF state into it — eliminating the per-field\n * `<Controller render={...} />` boilerplate.\n *\n * @example\n * const form = useZodForm(schema);\n * <FormProvider {...form}>\n * <Form>\n * <FormField name=\"email\" label=\"Email\" required>\n * <Input type=\"email\" />\n * </FormField>\n * <FormField name=\"cep\" label=\"CEP\">\n * <CEPInput />\n * </FormField>\n * </Form>\n * </FormProvider>;\n */\n/**\n * What is thrown when no `control` can be resolved.\n *\n * It names **two** causes, because the throw cannot tell them apart and the\n * second one is the expensive one. The obvious reading — no provider, no prop —\n * is usually right. But the identical throw happens with a `<FormProvider>`\n * mounted directly above, when the app and the SDK resolve two different copies\n * of `react-hook-form`: the provider publishes on the app copy's context and\n * `useFormContext` here reads the SDK copy's, which is empty. Someone looking at\n * a provider they can see, being told it is missing, does not go looking at\n * `node_modules` — so the message has to send them there.\n */\nconst NO_CONTROL_MESSAGE =\n \"FormField found no form to bind to. Either pass a `control` prop, or mount a \" +\n \"<FormProvider> above it. If a <FormProvider> IS mounted above it, the app and the \" +\n \"SDK are resolving two copies of react-hook-form: the provider publishes on one \" +\n \"copy's context and this field reads the other's. \" +\n DUPLICATE_COPY_REMEDY;\n\nexport function FormField<\n TValues extends FieldValues = FieldValues,\n TName extends FieldPath<TValues> = FieldPath<TValues>,\n>({ name, label, helperText, required, control, children }: FormFieldProps<TValues, TName>) {\n const context = useFormContext<TValues>();\n const resolvedControl = control ?? context?.control;\n if (!resolvedControl) {\n throw new Error(NO_CONTROL_MESSAGE);\n }\n\n return (\n <Controller\n name={name}\n control={resolvedControl}\n render={({ field, fieldState }) => {\n if (!isValidElement(children)) return children;\n const errorMessage = fieldState.error?.message;\n return cloneElement(children as ReactElement<FormFieldChildProps>, {\n name: field.name,\n value: field.value,\n onChange: field.onChange,\n onBlur: field.onBlur,\n ref: field.ref,\n label,\n helperText: errorMessage ? undefined : helperText,\n error: errorMessage,\n required,\n \"aria-invalid\": !!errorMessage,\n });\n }}\n />\n );\n}\n"],"mappings":";;;;;AA0FA,IAAM,IACF,oSAIA;AAEJ,SAAgB,EAGd,EAAE,SAAM,UAAO,eAAY,aAAU,YAAS,eAA4C;CACxF,IAAM,IAAU,EAAwB,GAClC,IAAkB,KAAW,GAAS;CAC5C,IAAI,CAAC,GACD,MAAU,MAAM,CAAkB;CAGtC,OACI,kBAAC,GAAD;EACU;EACN,SAAS;EACT,SAAS,EAAE,UAAO,oBAAiB;GAC/B,IAAI,CAAC,EAAe,CAAQ,GAAG,OAAO;GACtC,IAAM,IAAe,EAAW,OAAO;GACvC,OAAO,EAAa,GAA+C;IAC/D,MAAM,EAAM;IACZ,OAAO,EAAM;IACb,UAAU,EAAM;IAChB,QAAQ,EAAM;IACd,KAAK,EAAM;IACX;IACA,YAAY,IAAe,KAAA,IAAY;IACvC,OAAO;IACP;IACA,gBAAgB,CAAC,CAAC;GACtB,CAAC;EACL;CACH,CAAA;AAET"}
@@ -1,2 +1,2 @@
1
- const e=require("../components/Input/Input.cjs"),t=require("../utils/format.cjs"),n=require("./br-validators.cjs");let r=require("react"),i=require("react/jsx-runtime");function a(t,n=`numeric`){return(0,r.forwardRef)(function({value:r,onChange:a,...o},s){return(0,i.jsx)(e.Input,{...o,ref:s,value:t(r??``),inputMode:n,onChange:e=>a?.(t(e.target.value))})})}var o=a(t.formatCPF),s=a(n.formatCNPJ),c=a(t.formatPhone,`tel`),l=a(n.formatCEP);function u(e,t,n){return new Intl.NumberFormat(t,{style:`currency`,currency:n}).format(e/100)}function d(e){let t=e.replace(/\D/g,``);return t?Number.parseInt(t,10):0}var f=(0,r.forwardRef)(function({value:t,onChange:n,currency:r=`BRL`,locale:a=`pt-BR`,...o},s){return(0,i.jsx)(e.Input,{...o,ref:s,type:`text`,inputMode:`numeric`,value:u(t||0,a,r),onChange:e=>n(d(e.target.value))})});exports.CEPInput=l,exports.CNPJInput=s,exports.CPFInput=o,exports.MoneyInput=f,exports.PhoneInput=c;
1
+ const e=require("../components/Input/Input.cjs"),t=require("../utils/intl-cache.cjs"),n=require("../utils/format.cjs"),r=require("./br-validators.cjs");let i=require("react"),a=require("react/jsx-runtime");function o(t,n=`numeric`){return(0,i.forwardRef)(function({value:r,onChange:i,...o},s){return(0,a.jsx)(e.Input,{...o,ref:s,value:t(r??``),inputMode:n,onChange:e=>i?.(t(e.target.value))})})}var s=o(n.formatCPF),c=o(r.formatCNPJ),l=o(n.formatPhone,`tel`),u=o(r.formatCEP);function d(e,n,r){return t.numberFormat(n,{style:`currency`,currency:r}).format(e/100)}function f(e){let t=e.replace(/\D/g,``);return t?Number.parseInt(t,10):0}var p=(0,i.forwardRef)(function({value:t,onChange:n,currency:r=`BRL`,locale:i=`pt-BR`,...o},s){return(0,a.jsx)(e.Input,{...o,ref:s,type:`text`,inputMode:`numeric`,value:d(t||0,i,r),onChange:e=>n(f(e.target.value))})});exports.CEPInput=u,exports.CNPJInput=c,exports.CPFInput=s,exports.MoneyInput=p,exports.PhoneInput=l;
2
2
  //# sourceMappingURL=masked-inputs.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"masked-inputs.cjs","names":[],"sources":["../../src/forms/masked-inputs.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { InputHTMLAttributes } from \"react\";\nimport { Input, type InputProps } from \"@/components/Input\";\nimport { formatCEP, formatCNPJ } from \"./br-validators\";\nimport { formatCPF, formatPhone } from \"@/utils/format\";\n\n/**\n * Props of every masked input.\n *\n * `value` and `onChange` are optional because the primary documented usage is\n * inside `<FormField>`, which supplies both through `cloneElement` — declaring\n * them required made `<FormField name=\"cpf\"><CPFInput /></FormField>` fail to\n * type-check while working perfectly at runtime. Standalone usage still passes\n * both; an uncontrolled input without `onChange` simply reports nothing.\n */\ntype MaskedFieldProps = Omit<InputProps, \"value\" | \"onChange\"> & {\n value?: string;\n onChange?: (value: string) => void;\n};\n\nfunction maskedInput(\n mask: (input: string) => string,\n inputMode: InputHTMLAttributes<HTMLInputElement>[\"inputMode\"] = \"numeric\",\n) {\n return forwardRef<HTMLInputElement, MaskedFieldProps>(function MaskedInput(\n { value, onChange, ...props },\n ref,\n ) {\n return (\n <Input\n {...props}\n ref={ref}\n value={mask(value ?? \"\")}\n inputMode={inputMode}\n onChange={(event) => onChange?.(mask(event.target.value))}\n />\n );\n });\n}\n\nexport const CPFInput = maskedInput(formatCPF);\nexport const CNPJInput = maskedInput(formatCNPJ);\nexport const PhoneInput = maskedInput(formatPhone, \"tel\");\nexport const CEPInput = maskedInput(formatCEP);\n\nexport interface MoneyInputProps extends Omit<InputProps, \"value\" | \"onChange\" | \"type\"> {\n /** Cents (integer). Internally treated as 1/100 of the currency unit. */\n value: number;\n onChange: (cents: number) => void;\n /** Currency code for `Intl.NumberFormat`. Default: `\"BRL\"`. */\n currency?: string;\n /** Locale for `Intl.NumberFormat`. Default: `\"pt-BR\"`. */\n locale?: string;\n}\n\nfunction formatCents(cents: number, locale: string, currency: string): string {\n return new Intl.NumberFormat(locale, { style: \"currency\", currency }).format(cents / 100);\n}\n\nfunction parseCents(text: string): number {\n const digits = text.replace(/\\D/g, \"\");\n if (!digits) return 0;\n return Number.parseInt(digits, 10);\n}\n\n/**\n * Currency-masked input. Stores the value as an integer number of cents to\n * avoid floating-point error. Suitable for `react-hook-form` once you adapt\n * the field to expose cents.\n */\nexport const MoneyInput = forwardRef<HTMLInputElement, MoneyInputProps>(function MoneyInput(\n { value, onChange, currency = \"BRL\", locale = \"pt-BR\", ...props },\n ref,\n) {\n return (\n <Input\n {...props}\n ref={ref}\n type=\"text\"\n inputMode=\"numeric\"\n value={formatCents(value || 0, locale, currency)}\n onChange={(event) => onChange(parseCents(event.target.value))}\n />\n );\n});\n"],"mappings":"yKAoBA,SAAS,EACL,EACA,EAAgE,UAClE,CACE,OAAA,EAAO,EAAA,WAAA,CAA+C,SAClD,CAAE,QAAO,WAAU,GAAG,GACtB,EACF,CACE,OACI,EAAA,EAAA,IAAA,CAAC,EAAA,MAAD,CACI,GAAI,EACC,MACL,MAAO,EAAK,GAAS,EAAE,EACZ,YACX,SAAW,GAAU,IAAW,EAAK,EAAM,OAAO,KAAK,CAAC,CAC3D,CAAA,CAET,CAAC,CACL,CAEA,IAAa,EAAW,EAAY,EAAA,SAAS,EAChC,EAAY,EAAY,EAAA,UAAU,EAClC,EAAa,EAAY,EAAA,YAAa,KAAK,EAC3C,EAAW,EAAY,EAAA,SAAS,EAY7C,SAAS,EAAY,EAAe,EAAgB,EAA0B,CAC1E,OAAO,IAAI,KAAK,aAAa,EAAQ,CAAE,MAAO,WAAY,UAAS,CAAC,CAAC,CAAC,OAAO,EAAQ,GAAG,CAC5F,CAEA,SAAS,EAAW,EAAsB,CACtC,IAAM,EAAS,EAAK,QAAQ,MAAO,EAAE,EAErC,OADK,EACE,OAAO,SAAS,EAAQ,EAAE,EADb,CAExB,CAOA,IAAa,GAAA,EAAa,EAAA,WAAA,CAA8C,SACpE,CAAE,QAAO,WAAU,WAAW,MAAO,SAAS,QAAS,GAAG,GAC1D,EACF,CACE,OACI,EAAA,EAAA,IAAA,CAAC,EAAA,MAAD,CACI,GAAI,EACC,MACL,KAAK,OACL,UAAU,UACV,MAAO,EAAY,GAAS,EAAG,EAAQ,CAAQ,EAC/C,SAAW,GAAU,EAAS,EAAW,EAAM,OAAO,KAAK,CAAC,CAC/D,CAAA,CAET,CAAC"}
1
+ {"version":3,"file":"masked-inputs.cjs","names":[],"sources":["../../src/forms/masked-inputs.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { InputHTMLAttributes } from \"react\";\nimport { Input, type InputProps } from \"@/components/Input\";\nimport { formatCEP, formatCNPJ } from \"./br-validators\";\nimport { formatCPF, formatPhone } from \"@/utils/format\";\nimport { numberFormat } from \"@/utils/intl-cache\";\n\n/**\n * Props of every masked input.\n *\n * `value` and `onChange` are optional because the primary documented usage is\n * inside `<FormField>`, which supplies both through `cloneElement` — declaring\n * them required made `<FormField name=\"cpf\"><CPFInput /></FormField>` fail to\n * type-check while working perfectly at runtime. Standalone usage still passes\n * both; an uncontrolled input without `onChange` simply reports nothing.\n */\ntype MaskedFieldProps = Omit<InputProps, \"value\" | \"onChange\"> & {\n value?: string;\n onChange?: (value: string) => void;\n};\n\nfunction maskedInput(\n mask: (input: string) => string,\n inputMode: InputHTMLAttributes<HTMLInputElement>[\"inputMode\"] = \"numeric\",\n) {\n return forwardRef<HTMLInputElement, MaskedFieldProps>(function MaskedInput(\n { value, onChange, ...props },\n ref,\n ) {\n return (\n <Input\n {...props}\n ref={ref}\n value={mask(value ?? \"\")}\n inputMode={inputMode}\n onChange={(event) => onChange?.(mask(event.target.value))}\n />\n );\n });\n}\n\nexport const CPFInput = maskedInput(formatCPF);\nexport const CNPJInput = maskedInput(formatCNPJ);\nexport const PhoneInput = maskedInput(formatPhone, \"tel\");\nexport const CEPInput = maskedInput(formatCEP);\n\nexport interface MoneyInputProps extends Omit<InputProps, \"value\" | \"onChange\" | \"type\"> {\n /** Cents (integer). Internally treated as 1/100 of the currency unit. */\n value: number;\n onChange: (cents: number) => void;\n /** Currency code for `Intl.NumberFormat`. Default: `\"BRL\"`. */\n currency?: string;\n /** Locale for `Intl.NumberFormat`. Default: `\"pt-BR\"`. */\n locale?: string;\n}\n\nfunction formatCents(cents: number, locale: string, currency: string): string {\n return numberFormat(locale, { style: \"currency\", currency }).format(cents / 100);\n}\n\nfunction parseCents(text: string): number {\n const digits = text.replace(/\\D/g, \"\");\n if (!digits) return 0;\n return Number.parseInt(digits, 10);\n}\n\n/**\n * Currency-masked input. Stores the value as an integer number of cents to\n * avoid floating-point error. Suitable for `react-hook-form` once you adapt\n * the field to expose cents.\n */\nexport const MoneyInput = forwardRef<HTMLInputElement, MoneyInputProps>(function MoneyInput(\n { value, onChange, currency = \"BRL\", locale = \"pt-BR\", ...props },\n ref,\n) {\n return (\n <Input\n {...props}\n ref={ref}\n type=\"text\"\n inputMode=\"numeric\"\n value={formatCents(value || 0, locale, currency)}\n onChange={(event) => onChange(parseCents(event.target.value))}\n />\n );\n});\n"],"mappings":"8MAqBA,SAAS,EACL,EACA,EAAgE,UAClE,CACE,OAAA,EAAO,EAAA,WAAA,CAA+C,SAClD,CAAE,QAAO,WAAU,GAAG,GACtB,EACF,CACE,OACI,EAAA,EAAA,IAAA,CAAC,EAAA,MAAD,CACI,GAAI,EACC,MACL,MAAO,EAAK,GAAS,EAAE,EACZ,YACX,SAAW,GAAU,IAAW,EAAK,EAAM,OAAO,KAAK,CAAC,CAC3D,CAAA,CAET,CAAC,CACL,CAEA,IAAa,EAAW,EAAY,EAAA,SAAS,EAChC,EAAY,EAAY,EAAA,UAAU,EAClC,EAAa,EAAY,EAAA,YAAa,KAAK,EAC3C,EAAW,EAAY,EAAA,SAAS,EAY7C,SAAS,EAAY,EAAe,EAAgB,EAA0B,CAC1E,OAAO,EAAA,aAAa,EAAQ,CAAE,MAAO,WAAY,UAAS,CAAC,CAAC,CAAC,OAAO,EAAQ,GAAG,CACnF,CAEA,SAAS,EAAW,EAAsB,CACtC,IAAM,EAAS,EAAK,QAAQ,MAAO,EAAE,EAErC,OADK,EACE,OAAO,SAAS,EAAQ,EAAE,EADb,CAExB,CAOA,IAAa,GAAA,EAAa,EAAA,WAAA,CAA8C,SACpE,CAAE,QAAO,WAAU,WAAW,MAAO,SAAS,QAAS,GAAG,GAC1D,EACF,CACE,OACI,EAAA,EAAA,IAAA,CAAC,EAAA,MAAD,CACI,GAAI,EACC,MACL,KAAK,OACL,UAAU,UACV,MAAO,EAAY,GAAS,EAAG,EAAQ,CAAQ,EAC/C,SAAW,GAAU,EAAS,EAAW,EAAM,OAAO,KAAK,CAAC,CAC/D,CAAA,CAET,CAAC"}
@@ -1,42 +1,43 @@
1
1
  import { Input as e } from "../components/Input/Input.js";
2
- import { formatCPF as t, formatPhone as n } from "../utils/format.js";
3
- import { formatCEP as r, formatCNPJ as i } from "./br-validators.js";
4
- import { forwardRef as a } from "react";
5
- import { jsx as o } from "react/jsx-runtime";
2
+ import { numberFormat as t } from "../utils/intl-cache.js";
3
+ import { formatCPF as n, formatPhone as r } from "../utils/format.js";
4
+ import { formatCEP as i, formatCNPJ as a } from "./br-validators.js";
5
+ import { forwardRef as o } from "react";
6
+ import { jsx as s } from "react/jsx-runtime";
6
7
  //#region src/forms/masked-inputs.tsx
7
- function s(t, n = "numeric") {
8
- return a(function({ value: r, onChange: i, ...a }, s) {
9
- return /* @__PURE__ */ o(e, {
8
+ function c(t, n = "numeric") {
9
+ return o(function({ value: r, onChange: i, ...a }, o) {
10
+ return /* @__PURE__ */ s(e, {
10
11
  ...a,
11
- ref: s,
12
+ ref: o,
12
13
  value: t(r ?? ""),
13
14
  inputMode: n,
14
15
  onChange: (e) => i?.(t(e.target.value))
15
16
  });
16
17
  });
17
18
  }
18
- var c = s(t), l = s(i), u = s(n, "tel"), d = s(r);
19
- function f(e, t, n) {
20
- return new Intl.NumberFormat(t, {
19
+ var l = c(n), u = c(a), d = c(r, "tel"), f = c(i);
20
+ function p(e, n, r) {
21
+ return t(n, {
21
22
  style: "currency",
22
- currency: n
23
+ currency: r
23
24
  }).format(e / 100);
24
25
  }
25
- function p(e) {
26
+ function m(e) {
26
27
  let t = e.replace(/\D/g, "");
27
28
  return t ? Number.parseInt(t, 10) : 0;
28
29
  }
29
- var m = a(function({ value: t, onChange: n, currency: r = "BRL", locale: i = "pt-BR", ...a }, s) {
30
- return /* @__PURE__ */ o(e, {
30
+ var h = o(function({ value: t, onChange: n, currency: r = "BRL", locale: i = "pt-BR", ...a }, o) {
31
+ return /* @__PURE__ */ s(e, {
31
32
  ...a,
32
- ref: s,
33
+ ref: o,
33
34
  type: "text",
34
35
  inputMode: "numeric",
35
- value: f(t || 0, i, r),
36
- onChange: (e) => n(p(e.target.value))
36
+ value: p(t || 0, i, r),
37
+ onChange: (e) => n(m(e.target.value))
37
38
  });
38
39
  });
39
40
  //#endregion
40
- export { d as CEPInput, l as CNPJInput, c as CPFInput, m as MoneyInput, u as PhoneInput };
41
+ export { f as CEPInput, u as CNPJInput, l as CPFInput, h as MoneyInput, d as PhoneInput };
41
42
 
42
43
  //# sourceMappingURL=masked-inputs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"masked-inputs.js","names":[],"sources":["../../src/forms/masked-inputs.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { InputHTMLAttributes } from \"react\";\nimport { Input, type InputProps } from \"@/components/Input\";\nimport { formatCEP, formatCNPJ } from \"./br-validators\";\nimport { formatCPF, formatPhone } from \"@/utils/format\";\n\n/**\n * Props of every masked input.\n *\n * `value` and `onChange` are optional because the primary documented usage is\n * inside `<FormField>`, which supplies both through `cloneElement` — declaring\n * them required made `<FormField name=\"cpf\"><CPFInput /></FormField>` fail to\n * type-check while working perfectly at runtime. Standalone usage still passes\n * both; an uncontrolled input without `onChange` simply reports nothing.\n */\ntype MaskedFieldProps = Omit<InputProps, \"value\" | \"onChange\"> & {\n value?: string;\n onChange?: (value: string) => void;\n};\n\nfunction maskedInput(\n mask: (input: string) => string,\n inputMode: InputHTMLAttributes<HTMLInputElement>[\"inputMode\"] = \"numeric\",\n) {\n return forwardRef<HTMLInputElement, MaskedFieldProps>(function MaskedInput(\n { value, onChange, ...props },\n ref,\n ) {\n return (\n <Input\n {...props}\n ref={ref}\n value={mask(value ?? \"\")}\n inputMode={inputMode}\n onChange={(event) => onChange?.(mask(event.target.value))}\n />\n );\n });\n}\n\nexport const CPFInput = maskedInput(formatCPF);\nexport const CNPJInput = maskedInput(formatCNPJ);\nexport const PhoneInput = maskedInput(formatPhone, \"tel\");\nexport const CEPInput = maskedInput(formatCEP);\n\nexport interface MoneyInputProps extends Omit<InputProps, \"value\" | \"onChange\" | \"type\"> {\n /** Cents (integer). Internally treated as 1/100 of the currency unit. */\n value: number;\n onChange: (cents: number) => void;\n /** Currency code for `Intl.NumberFormat`. Default: `\"BRL\"`. */\n currency?: string;\n /** Locale for `Intl.NumberFormat`. Default: `\"pt-BR\"`. */\n locale?: string;\n}\n\nfunction formatCents(cents: number, locale: string, currency: string): string {\n return new Intl.NumberFormat(locale, { style: \"currency\", currency }).format(cents / 100);\n}\n\nfunction parseCents(text: string): number {\n const digits = text.replace(/\\D/g, \"\");\n if (!digits) return 0;\n return Number.parseInt(digits, 10);\n}\n\n/**\n * Currency-masked input. Stores the value as an integer number of cents to\n * avoid floating-point error. Suitable for `react-hook-form` once you adapt\n * the field to expose cents.\n */\nexport const MoneyInput = forwardRef<HTMLInputElement, MoneyInputProps>(function MoneyInput(\n { value, onChange, currency = \"BRL\", locale = \"pt-BR\", ...props },\n ref,\n) {\n return (\n <Input\n {...props}\n ref={ref}\n type=\"text\"\n inputMode=\"numeric\"\n value={formatCents(value || 0, locale, currency)}\n onChange={(event) => onChange(parseCents(event.target.value))}\n />\n );\n});\n"],"mappings":";;;;;;AAoBA,SAAS,EACL,GACA,IAAgE,WAClE;CACE,OAAO,EAA+C,SAClD,EAAE,UAAO,aAAU,GAAG,KACtB,GACF;EACE,OACI,kBAAC,GAAD;GACI,GAAI;GACC;GACL,OAAO,EAAK,KAAS,EAAE;GACZ;GACX,WAAW,MAAU,IAAW,EAAK,EAAM,OAAO,KAAK,CAAC;EAC3D,CAAA;CAET,CAAC;AACL;AAEA,IAAa,IAAW,EAAY,CAAS,GAChC,IAAY,EAAY,CAAU,GAClC,IAAa,EAAY,GAAa,KAAK,GAC3C,IAAW,EAAY,CAAS;AAY7C,SAAS,EAAY,GAAe,GAAgB,GAA0B;CAC1E,OAAO,IAAI,KAAK,aAAa,GAAQ;EAAE,OAAO;EAAY;CAAS,CAAC,CAAC,CAAC,OAAO,IAAQ,GAAG;AAC5F;AAEA,SAAS,EAAW,GAAsB;CACtC,IAAM,IAAS,EAAK,QAAQ,OAAO,EAAE;CAErC,OADK,IACE,OAAO,SAAS,GAAQ,EAAE,IADb;AAExB;AAOA,IAAa,IAAa,EAA8C,SACpE,EAAE,UAAO,aAAU,cAAW,OAAO,YAAS,SAAS,GAAG,KAC1D,GACF;CACE,OACI,kBAAC,GAAD;EACI,GAAI;EACC;EACL,MAAK;EACL,WAAU;EACV,OAAO,EAAY,KAAS,GAAG,GAAQ,CAAQ;EAC/C,WAAW,MAAU,EAAS,EAAW,EAAM,OAAO,KAAK,CAAC;CAC/D,CAAA;AAET,CAAC"}
1
+ {"version":3,"file":"masked-inputs.js","names":[],"sources":["../../src/forms/masked-inputs.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { InputHTMLAttributes } from \"react\";\nimport { Input, type InputProps } from \"@/components/Input\";\nimport { formatCEP, formatCNPJ } from \"./br-validators\";\nimport { formatCPF, formatPhone } from \"@/utils/format\";\nimport { numberFormat } from \"@/utils/intl-cache\";\n\n/**\n * Props of every masked input.\n *\n * `value` and `onChange` are optional because the primary documented usage is\n * inside `<FormField>`, which supplies both through `cloneElement` — declaring\n * them required made `<FormField name=\"cpf\"><CPFInput /></FormField>` fail to\n * type-check while working perfectly at runtime. Standalone usage still passes\n * both; an uncontrolled input without `onChange` simply reports nothing.\n */\ntype MaskedFieldProps = Omit<InputProps, \"value\" | \"onChange\"> & {\n value?: string;\n onChange?: (value: string) => void;\n};\n\nfunction maskedInput(\n mask: (input: string) => string,\n inputMode: InputHTMLAttributes<HTMLInputElement>[\"inputMode\"] = \"numeric\",\n) {\n return forwardRef<HTMLInputElement, MaskedFieldProps>(function MaskedInput(\n { value, onChange, ...props },\n ref,\n ) {\n return (\n <Input\n {...props}\n ref={ref}\n value={mask(value ?? \"\")}\n inputMode={inputMode}\n onChange={(event) => onChange?.(mask(event.target.value))}\n />\n );\n });\n}\n\nexport const CPFInput = maskedInput(formatCPF);\nexport const CNPJInput = maskedInput(formatCNPJ);\nexport const PhoneInput = maskedInput(formatPhone, \"tel\");\nexport const CEPInput = maskedInput(formatCEP);\n\nexport interface MoneyInputProps extends Omit<InputProps, \"value\" | \"onChange\" | \"type\"> {\n /** Cents (integer). Internally treated as 1/100 of the currency unit. */\n value: number;\n onChange: (cents: number) => void;\n /** Currency code for `Intl.NumberFormat`. Default: `\"BRL\"`. */\n currency?: string;\n /** Locale for `Intl.NumberFormat`. Default: `\"pt-BR\"`. */\n locale?: string;\n}\n\nfunction formatCents(cents: number, locale: string, currency: string): string {\n return numberFormat(locale, { style: \"currency\", currency }).format(cents / 100);\n}\n\nfunction parseCents(text: string): number {\n const digits = text.replace(/\\D/g, \"\");\n if (!digits) return 0;\n return Number.parseInt(digits, 10);\n}\n\n/**\n * Currency-masked input. Stores the value as an integer number of cents to\n * avoid floating-point error. Suitable for `react-hook-form` once you adapt\n * the field to expose cents.\n */\nexport const MoneyInput = forwardRef<HTMLInputElement, MoneyInputProps>(function MoneyInput(\n { value, onChange, currency = \"BRL\", locale = \"pt-BR\", ...props },\n ref,\n) {\n return (\n <Input\n {...props}\n ref={ref}\n type=\"text\"\n inputMode=\"numeric\"\n value={formatCents(value || 0, locale, currency)}\n onChange={(event) => onChange(parseCents(event.target.value))}\n />\n );\n});\n"],"mappings":";;;;;;;AAqBA,SAAS,EACL,GACA,IAAgE,WAClE;CACE,OAAO,EAA+C,SAClD,EAAE,UAAO,aAAU,GAAG,KACtB,GACF;EACE,OACI,kBAAC,GAAD;GACI,GAAI;GACC;GACL,OAAO,EAAK,KAAS,EAAE;GACZ;GACX,WAAW,MAAU,IAAW,EAAK,EAAM,OAAO,KAAK,CAAC;EAC3D,CAAA;CAET,CAAC;AACL;AAEA,IAAa,IAAW,EAAY,CAAS,GAChC,IAAY,EAAY,CAAU,GAClC,IAAa,EAAY,GAAa,KAAK,GAC3C,IAAW,EAAY,CAAS;AAY7C,SAAS,EAAY,GAAe,GAAgB,GAA0B;CAC1E,OAAO,EAAa,GAAQ;EAAE,OAAO;EAAY;CAAS,CAAC,CAAC,CAAC,OAAO,IAAQ,GAAG;AACnF;AAEA,SAAS,EAAW,GAAsB;CACtC,IAAM,IAAS,EAAK,QAAQ,OAAO,EAAE;CAErC,OADK,IACE,OAAO,SAAS,GAAQ,EAAE,IADb;AAExB;AAOA,IAAa,IAAa,EAA8C,SACpE,EAAE,UAAO,aAAU,cAAW,OAAO,YAAS,SAAS,GAAG,KAC1D,GACF;CACE,OACI,kBAAC,GAAD;EACI,GAAI;EACC;EACL,MAAK;EACL,WAAU;EACV,OAAO,EAAY,KAAS,GAAG,GAAQ,CAAQ;EAC/C,WAAW,MAAU,EAAS,EAAW,EAAM,OAAO,KAAK,CAAC;CAC/D,CAAA;AAET,CAAC"}
@@ -0,0 +1,2 @@
1
+ let e=require("react");function t(){if(typeof document>`u`)return null;let e=document;return document.fullscreenElement??e.webkitFullscreenElement??null}function n(){let[n,r]=(0,e.useState)(t);return(0,e.useEffect)(()=>{let e=()=>r(t());return e(),document.addEventListener(`fullscreenchange`,e),document.addEventListener(`webkitfullscreenchange`,e),()=>{document.removeEventListener(`fullscreenchange`,e),document.removeEventListener(`webkitfullscreenchange`,e)}},[]),n}exports.getFullscreenElement=t,exports.useFullscreenElement=n;
2
+ //# sourceMappingURL=use-fullscreen-element.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-fullscreen-element.cjs","names":[],"sources":["../../src/hooks/use-fullscreen-element.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\n/**\n * Vendor-prefixed fullscreen member of `document`, still shipped by WebKit.\n *\n * Declared optional on purpose: the standard property is what every other engine\n * answers to, and Safari is the only reason the second read exists.\n */\ninterface WebkitFullscreenDocument {\n webkitFullscreenElement?: Element | null;\n}\n\n/**\n * Read the element the browser is presenting fullscreen, standard property first.\n *\n * A plain function rather than a hook, because two very different callers need\n * the answer: `useFullscreenElement` below, which turns it into state, and the\n * action callbacks of `useFullscreen`, which need the value *at call time* and\n * cannot wait for a render to have happened since the last change.\n *\n * @returns The element being presented fullscreen, or `null` — including in any\n * environment without a `document` (a service worker, a build plugin, a Node\n * test), where the SDK must not throw.\n */\nexport function getFullscreenElement(): Element | null {\n if (typeof document === \"undefined\") return null;\n const prefixed = document as Document & WebkitFullscreenDocument;\n return document.fullscreenElement ?? prefixed.webkitFullscreenElement ?? null;\n}\n\n/**\n * Track the element the browser is presenting fullscreen.\n *\n * The SDK's single subscription to `fullscreenchange` (and WebKit's\n * `webkitfullscreenchange`). Two features need exactly this fact and would\n * otherwise each carry their own copy of the prefix dance: `usePortalHost` asks\n * *where do I mount* — the fullscreen element paints its own subtree and nothing\n * else, so a dialog portalled to `document.body` is invisible while fullscreen is\n * on — and `useFullscreen` asks *is my element the one presented*. One\n * subscription, two questions.\n *\n * The event is the source of truth rather than the return of `requestFullscreen`\n * / `exitFullscreen`, because `Esc`, the browser's own exit affordance and F11\n * leave fullscreen without ever passing through those calls.\n *\n * The first value is resolved during render rather than in the effect, so a\n * consumer that mounts while fullscreen is already active is correct in its very\n * first commit instead of correcting itself one frame later.\n *\n * @returns The fullscreen element, or `null` when nothing is presented.\n */\nexport function useFullscreenElement(): Element | null {\n const [element, setElement] = useState<Element | null>(getFullscreenElement);\n\n useEffect(() => {\n const sync = (): void => setElement(getFullscreenElement());\n sync();\n document.addEventListener(\"fullscreenchange\", sync);\n document.addEventListener(\"webkitfullscreenchange\", sync);\n return () => {\n document.removeEventListener(\"fullscreenchange\", sync);\n document.removeEventListener(\"webkitfullscreenchange\", sync);\n };\n }, []);\n\n return element;\n}\n"],"mappings":"uBAwBA,SAAgB,GAAuC,CACnD,GAAI,OAAO,SAAa,IAAa,OAAO,KAC5C,IAAM,EAAW,SACjB,OAAO,SAAS,mBAAqB,EAAS,yBAA2B,IAC7E,CAuBA,SAAgB,GAAuC,CACnD,GAAM,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAAyB,CAAoB,EAa3E,OAXA,EAAA,EAAA,UAAA,KAAgB,CACZ,IAAM,MAAmB,EAAW,EAAqB,CAAC,EAI1D,OAHA,EAAK,EACL,SAAS,iBAAiB,mBAAoB,CAAI,EAClD,SAAS,iBAAiB,yBAA0B,CAAI,MAC3C,CACT,SAAS,oBAAoB,mBAAoB,CAAI,EACrD,SAAS,oBAAoB,yBAA0B,CAAI,CAC/D,CACJ,EAAG,CAAC,CAAC,EAEE,CACX"}
@@ -0,0 +1,20 @@
1
+ import { useEffect as e, useState as t } from "react";
2
+ //#region src/hooks/use-fullscreen-element.ts
3
+ function n() {
4
+ if (typeof document > "u") return null;
5
+ let e = document;
6
+ return document.fullscreenElement ?? e.webkitFullscreenElement ?? null;
7
+ }
8
+ function r() {
9
+ let [r, i] = t(n);
10
+ return e(() => {
11
+ let e = () => i(n());
12
+ return e(), document.addEventListener("fullscreenchange", e), document.addEventListener("webkitfullscreenchange", e), () => {
13
+ document.removeEventListener("fullscreenchange", e), document.removeEventListener("webkitfullscreenchange", e);
14
+ };
15
+ }, []), r;
16
+ }
17
+ //#endregion
18
+ export { n as getFullscreenElement, r as useFullscreenElement };
19
+
20
+ //# sourceMappingURL=use-fullscreen-element.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-fullscreen-element.js","names":[],"sources":["../../src/hooks/use-fullscreen-element.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\n/**\n * Vendor-prefixed fullscreen member of `document`, still shipped by WebKit.\n *\n * Declared optional on purpose: the standard property is what every other engine\n * answers to, and Safari is the only reason the second read exists.\n */\ninterface WebkitFullscreenDocument {\n webkitFullscreenElement?: Element | null;\n}\n\n/**\n * Read the element the browser is presenting fullscreen, standard property first.\n *\n * A plain function rather than a hook, because two very different callers need\n * the answer: `useFullscreenElement` below, which turns it into state, and the\n * action callbacks of `useFullscreen`, which need the value *at call time* and\n * cannot wait for a render to have happened since the last change.\n *\n * @returns The element being presented fullscreen, or `null` — including in any\n * environment without a `document` (a service worker, a build plugin, a Node\n * test), where the SDK must not throw.\n */\nexport function getFullscreenElement(): Element | null {\n if (typeof document === \"undefined\") return null;\n const prefixed = document as Document & WebkitFullscreenDocument;\n return document.fullscreenElement ?? prefixed.webkitFullscreenElement ?? null;\n}\n\n/**\n * Track the element the browser is presenting fullscreen.\n *\n * The SDK's single subscription to `fullscreenchange` (and WebKit's\n * `webkitfullscreenchange`). Two features need exactly this fact and would\n * otherwise each carry their own copy of the prefix dance: `usePortalHost` asks\n * *where do I mount* — the fullscreen element paints its own subtree and nothing\n * else, so a dialog portalled to `document.body` is invisible while fullscreen is\n * on — and `useFullscreen` asks *is my element the one presented*. One\n * subscription, two questions.\n *\n * The event is the source of truth rather than the return of `requestFullscreen`\n * / `exitFullscreen`, because `Esc`, the browser's own exit affordance and F11\n * leave fullscreen without ever passing through those calls.\n *\n * The first value is resolved during render rather than in the effect, so a\n * consumer that mounts while fullscreen is already active is correct in its very\n * first commit instead of correcting itself one frame later.\n *\n * @returns The fullscreen element, or `null` when nothing is presented.\n */\nexport function useFullscreenElement(): Element | null {\n const [element, setElement] = useState<Element | null>(getFullscreenElement);\n\n useEffect(() => {\n const sync = (): void => setElement(getFullscreenElement());\n sync();\n document.addEventListener(\"fullscreenchange\", sync);\n document.addEventListener(\"webkitfullscreenchange\", sync);\n return () => {\n document.removeEventListener(\"fullscreenchange\", sync);\n document.removeEventListener(\"webkitfullscreenchange\", sync);\n };\n }, []);\n\n return element;\n}\n"],"mappings":";;AAwBA,SAAgB,IAAuC;CACnD,IAAI,OAAO,WAAa,KAAa,OAAO;CAC5C,IAAM,IAAW;CACjB,OAAO,SAAS,qBAAqB,EAAS,2BAA2B;AAC7E;AAuBA,SAAgB,IAAuC;CACnD,IAAM,CAAC,GAAS,KAAc,EAAyB,CAAoB;CAa3E,OAXA,QAAgB;EACZ,IAAM,UAAmB,EAAW,EAAqB,CAAC;EAI1D,OAHA,EAAK,GACL,SAAS,iBAAiB,oBAAoB,CAAI,GAClD,SAAS,iBAAiB,0BAA0B,CAAI,SAC3C;GAET,AADA,SAAS,oBAAoB,oBAAoB,CAAI,GACrD,SAAS,oBAAoB,0BAA0B,CAAI;EAC/D;CACJ,GAAG,CAAC,CAAC,GAEE;AACX"}
@@ -0,0 +1,2 @@
1
+ const e=require("./use-fullscreen-element.cjs");let t=require("react");function n(e){return typeof document>`u`?null:e?e.current:document.documentElement}function r(){if(typeof document>`u`)return!1;let e=document.documentElement,t=document;return(typeof e.requestFullscreen==`function`||typeof e.webkitRequestFullscreen==`function`)&&(t.fullscreenEnabled??t.webkitFullscreenEnabled??!0)}function i(i){let a=e.useFullscreenElement(),[o]=(0,t.useState)(r),[s,c]=(0,t.useState)(!1);(0,t.useEffect)(()=>{let e=n(i);c(e!==null&&a===e)},[a,i]);let l=(0,t.useCallback)(async()=>{let e=n(i);if(e===null)throw Error(`useFullscreen: nothing to present. Either this environment has no document, or the ref was never attached to a mounted element.`);let t=e;if(typeof t.requestFullscreen==`function`){await t.requestFullscreen();return}if(typeof t.webkitRequestFullscreen==`function`){await t.webkitRequestFullscreen();return}throw Error(`useFullscreen: this browser exposes no way to enter fullscreen.`)},[i]),u=(0,t.useCallback)(async()=>{if(e.getFullscreenElement()===null)return;let t=document;if(typeof t.exitFullscreen==`function`){await t.exitFullscreen();return}if(typeof t.webkitExitFullscreen==`function`){await t.webkitExitFullscreen();return}throw Error(`useFullscreen: this browser exposes no way to leave fullscreen.`)},[]);return{isFullscreen:s,supported:o,enter:l,exit:u,toggle:(0,t.useCallback)(async()=>{let t=n(i);if(t!==null&&e.getFullscreenElement()===t){await u();return}await l()},[l,u,i])}}exports.isFullscreenSupported=r,exports.useFullscreen=i;
2
+ //# sourceMappingURL=use-fullscreen.cjs.map