tempest-react-sdk 0.39.0 → 0.40.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 (475) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +1 -1
  2. package/dist/access/access-control-context.cjs.map +1 -1
  3. package/dist/access/use-can.cjs.map +1 -1
  4. package/dist/app/AppProviders.cjs.map +1 -1
  5. package/dist/app/AppProviders.js.map +1 -1
  6. package/dist/audio/use-audio-recorder.cjs.map +1 -1
  7. package/dist/audio/use-audio.cjs.map +1 -1
  8. package/dist/audio/use-microphone.cjs.map +1 -1
  9. package/dist/auth/create-auth-store.cjs.map +1 -1
  10. package/dist/auth/lazy-with-retry.cjs.map +1 -1
  11. package/dist/auth/passkey.cjs.map +1 -1
  12. package/dist/auth/passkey.js.map +1 -1
  13. package/dist/auth/use-passkey.cjs.map +1 -1
  14. package/dist/br/BrazilMap.cjs +1 -1
  15. package/dist/br/BrazilMap.cjs.map +1 -1
  16. package/dist/br/BrazilMap.js +2 -2
  17. package/dist/br/BrazilMap.js.map +1 -1
  18. package/dist/br/BrazilStateCitySelect.cjs.map +1 -1
  19. package/dist/br/BrazilStateCitySelect.js.map +1 -1
  20. package/dist/br/BrazilStateMap.cjs +1 -1
  21. package/dist/br/BrazilStateMap.cjs.map +1 -1
  22. package/dist/br/BrazilStateMap.js +2 -2
  23. package/dist/br/BrazilStateMap.js.map +1 -1
  24. package/dist/br/MapLegend.cjs.map +1 -1
  25. package/dist/br/MapLegend.js.map +1 -1
  26. package/dist/br/MapMarkers.cjs.map +1 -1
  27. package/dist/br/MapMarkers.js.map +1 -1
  28. package/dist/br/MunicipalitySearch.cjs.map +1 -1
  29. package/dist/br/MunicipalitySearch.js.map +1 -1
  30. package/dist/br/PixQRCode.cjs.map +1 -1
  31. package/dist/br/PixQRCode.js.map +1 -1
  32. package/dist/br/use-map-hover.cjs.map +1 -1
  33. package/dist/br/use-map-zoom.cjs.map +1 -1
  34. package/dist/capture/media-recorder.cjs +1 -1
  35. package/dist/capture/media-recorder.js +2 -2
  36. package/dist/capture/use-barcode-scanner.cjs +1 -1
  37. package/dist/capture/use-barcode-scanner.cjs.map +1 -1
  38. package/dist/capture/use-barcode-scanner.js +2 -2
  39. package/dist/capture/use-barcode-scanner.js.map +1 -1
  40. package/dist/capture/use-screen-capture.cjs.map +1 -1
  41. package/dist/capture/use-speech-recognition.cjs.map +1 -1
  42. package/dist/capture/use-torch.cjs.map +1 -1
  43. package/dist/capture/use-video-recorder.cjs.map +1 -1
  44. package/dist/charts/AreaChart.cjs.map +1 -1
  45. package/dist/charts/AreaChart.js.map +1 -1
  46. package/dist/charts/BarChart.cjs.map +1 -1
  47. package/dist/charts/BarChart.js.map +1 -1
  48. package/dist/charts/LineChart.cjs.map +1 -1
  49. package/dist/charts/LineChart.js.map +1 -1
  50. package/dist/charts/PieChart.cjs.map +1 -1
  51. package/dist/charts/PieChart.js.map +1 -1
  52. package/dist/charts/RadarChart.cjs.map +1 -1
  53. package/dist/charts/RadarChart.js.map +1 -1
  54. package/dist/charts/use-chart-colors.cjs.map +1 -1
  55. package/dist/components/AIChat/AIChat.cjs.map +1 -1
  56. package/dist/components/AIChat/AIChat.js.map +1 -1
  57. package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
  58. package/dist/components/AIChat/AIChatComposer.js.map +1 -1
  59. package/dist/components/AIChat/AIChatTurn.cjs.map +1 -1
  60. package/dist/components/AIChat/AIChatTurn.js.map +1 -1
  61. package/dist/components/Accordion/Accordion.cjs.map +1 -1
  62. package/dist/components/Accordion/Accordion.js.map +1 -1
  63. package/dist/components/Alert/Alert.cjs.map +1 -1
  64. package/dist/components/Alert/Alert.js.map +1 -1
  65. package/dist/components/AppBar/AppBar.cjs.map +1 -1
  66. package/dist/components/AppBar/AppBar.js.map +1 -1
  67. package/dist/components/AppShell/AppShell.cjs.map +1 -1
  68. package/dist/components/AppShell/AppShell.js.map +1 -1
  69. package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -1
  70. package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -1
  71. package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -1
  72. package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -1
  73. package/dist/components/Avatar/Avatar.cjs.map +1 -1
  74. package/dist/components/Avatar/Avatar.js.map +1 -1
  75. package/dist/components/AvatarGroup/AvatarGroup.cjs.map +1 -1
  76. package/dist/components/AvatarGroup/AvatarGroup.js.map +1 -1
  77. package/dist/components/Badge/Badge.cjs.map +1 -1
  78. package/dist/components/Badge/Badge.js.map +1 -1
  79. package/dist/components/Banner/Banner.cjs.map +1 -1
  80. package/dist/components/Banner/Banner.js.map +1 -1
  81. package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -1
  82. package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -1
  83. package/dist/components/BottomNavigation/BottomNavigation.cjs.map +1 -1
  84. package/dist/components/BottomNavigation/BottomNavigation.js.map +1 -1
  85. package/dist/components/BottomSheet/BottomSheet.cjs.map +1 -1
  86. package/dist/components/BottomSheet/BottomSheet.js.map +1 -1
  87. package/dist/components/Breadcrumbs/Breadcrumbs.cjs.map +1 -1
  88. package/dist/components/Breadcrumbs/Breadcrumbs.js.map +1 -1
  89. package/dist/components/Button/Button.cjs.map +1 -1
  90. package/dist/components/Button/Button.js.map +1 -1
  91. package/dist/components/Calendar/Calendar.cjs +1 -1
  92. package/dist/components/Calendar/Calendar.cjs.map +1 -1
  93. package/dist/components/Calendar/Calendar.js +38 -41
  94. package/dist/components/Calendar/Calendar.js.map +1 -1
  95. package/dist/components/Card/Card.cjs.map +1 -1
  96. package/dist/components/Card/Card.js.map +1 -1
  97. package/dist/components/Carousel/Carousel.cjs.map +1 -1
  98. package/dist/components/Carousel/Carousel.js.map +1 -1
  99. package/dist/components/Chat/Chat.cjs.map +1 -1
  100. package/dist/components/Chat/Chat.js.map +1 -1
  101. package/dist/components/Chat/ChatComposer.cjs.map +1 -1
  102. package/dist/components/Chat/ChatComposer.js.map +1 -1
  103. package/dist/components/Chat/chat-groups.cjs +1 -1
  104. package/dist/components/Chat/chat-groups.cjs.map +1 -1
  105. package/dist/components/Chat/chat-groups.js +2 -2
  106. package/dist/components/Chat/chat-groups.js.map +1 -1
  107. package/dist/components/Checkbox/Checkbox.cjs.map +1 -1
  108. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  109. package/dist/components/ChipInput/ChipInput.cjs.map +1 -1
  110. package/dist/components/ChipInput/ChipInput.js.map +1 -1
  111. package/dist/components/ClickOutside/ClickOutside.cjs.map +1 -1
  112. package/dist/components/CodeBlock/CodeBlock.cjs.map +1 -1
  113. package/dist/components/CodeBlock/CodeBlock.js.map +1 -1
  114. package/dist/components/Collapsible/Collapsible.cjs.map +1 -1
  115. package/dist/components/Collapsible/Collapsible.js.map +1 -1
  116. package/dist/components/Combobox/Combobox.cjs.map +1 -1
  117. package/dist/components/Combobox/Combobox.js.map +1 -1
  118. package/dist/components/Command/Command.cjs.map +1 -1
  119. package/dist/components/Command/Command.js.map +1 -1
  120. package/dist/components/ConfirmDialog/ConfirmDialog.cjs.map +1 -1
  121. package/dist/components/ConfirmDialog/ConfirmDialog.js.map +1 -1
  122. package/dist/components/ContextMenu/ContextMenu.cjs.map +1 -1
  123. package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
  124. package/dist/components/CopyButton/CopyButton.cjs.map +1 -1
  125. package/dist/components/CopyButton/CopyButton.js.map +1 -1
  126. package/dist/components/DataList/DataList.cjs.map +1 -1
  127. package/dist/components/DataList/DataList.js.map +1 -1
  128. package/dist/components/DataTable/DataTable.cjs +1 -1
  129. package/dist/components/DataTable/DataTable.cjs.map +1 -1
  130. package/dist/components/DataTable/DataTable.js +2 -2
  131. package/dist/components/DataTable/DataTable.js.map +1 -1
  132. package/dist/components/DataTable/EditableCell.cjs.map +1 -1
  133. package/dist/components/DataTable/EditableCell.js.map +1 -1
  134. package/dist/components/DatePicker/DatePicker.cjs.map +1 -1
  135. package/dist/components/DateRangePicker/DateRangePicker.cjs.map +1 -1
  136. package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
  137. package/dist/components/DescriptionList/DescriptionList.cjs.map +1 -1
  138. package/dist/components/DescriptionList/DescriptionList.js.map +1 -1
  139. package/dist/components/Divider/Divider.cjs.map +1 -1
  140. package/dist/components/Divider/Divider.js.map +1 -1
  141. package/dist/components/Drawer/Drawer.cjs.map +1 -1
  142. package/dist/components/Drawer/Drawer.js.map +1 -1
  143. package/dist/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
  144. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  145. package/dist/components/Dropzone/Dropzone.cjs.map +1 -1
  146. package/dist/components/Dropzone/Dropzone.js.map +1 -1
  147. package/dist/components/EmptyState/EmptyState.cjs.map +1 -1
  148. package/dist/components/EmptyState/EmptyState.js.map +1 -1
  149. package/dist/components/ErrorState/ErrorState.cjs.map +1 -1
  150. package/dist/components/ErrorState/ErrorState.js.map +1 -1
  151. package/dist/components/FileUpload/FileUpload.cjs +1 -1
  152. package/dist/components/FileUpload/FileUpload.cjs.map +1 -1
  153. package/dist/components/FileUpload/FileUpload.js +1 -1
  154. package/dist/components/FileUpload/FileUpload.js.map +1 -1
  155. package/dist/components/FilterBar/FilterBar.cjs.map +1 -1
  156. package/dist/components/FilterBar/FilterBar.js.map +1 -1
  157. package/dist/components/FloatingActionButton/FloatingActionButton.cjs.map +1 -1
  158. package/dist/components/FloatingActionButton/FloatingActionButton.js.map +1 -1
  159. package/dist/components/Form/Form.cjs.map +1 -1
  160. package/dist/components/Form/Form.js.map +1 -1
  161. package/dist/components/HoverCard/HoverCard.cjs.map +1 -1
  162. package/dist/components/HoverCard/HoverCard.js.map +1 -1
  163. package/dist/components/Image/Image.cjs.map +1 -1
  164. package/dist/components/ImageCropper/ImageCropper.cjs +1 -1
  165. package/dist/components/ImageCropper/ImageCropper.cjs.map +1 -1
  166. package/dist/components/ImageCropper/ImageCropper.js +1 -1
  167. package/dist/components/ImageCropper/ImageCropper.js.map +1 -1
  168. package/dist/components/Input/Input.cjs.map +1 -1
  169. package/dist/components/Input/Input.js.map +1 -1
  170. package/dist/components/InstallBanner/InstallBanner.cjs.map +1 -1
  171. package/dist/components/InstallBanner/InstallBanner.js.map +1 -1
  172. package/dist/components/InstallButton/InstallButton.cjs.map +1 -1
  173. package/dist/components/InstallButton/InstallButton.js.map +1 -1
  174. package/dist/components/Kanban/Kanban.cjs.map +1 -1
  175. package/dist/components/Kanban/Kanban.js.map +1 -1
  176. package/dist/components/Label/Label.cjs.map +1 -1
  177. package/dist/components/Label/Label.js.map +1 -1
  178. package/dist/components/Lightbox/Lightbox.cjs.map +1 -1
  179. package/dist/components/Lightbox/Lightbox.js.map +1 -1
  180. package/dist/components/ListTile/ListTile.cjs.map +1 -1
  181. package/dist/components/ListTile/ListTile.js.map +1 -1
  182. package/dist/components/Markdown/Markdown.cjs +1 -1
  183. package/dist/components/Markdown/Markdown.cjs.map +1 -1
  184. package/dist/components/Markdown/Markdown.js +2 -2
  185. package/dist/components/Markdown/Markdown.js.map +1 -1
  186. package/dist/components/Masonry/Masonry.cjs.map +1 -1
  187. package/dist/components/Masonry/Masonry.js.map +1 -1
  188. package/dist/components/Menubar/Menubar.cjs.map +1 -1
  189. package/dist/components/Menubar/Menubar.js.map +1 -1
  190. package/dist/components/Modal/Modal.cjs.map +1 -1
  191. package/dist/components/Modal/Modal.js.map +1 -1
  192. package/dist/components/ModalsManager/ModalsManager.cjs.map +1 -1
  193. package/dist/components/ModalsManager/ModalsManager.js.map +1 -1
  194. package/dist/components/Money/Money.cjs.map +1 -1
  195. package/dist/components/Money/Money.js.map +1 -1
  196. package/dist/components/MultiSelect/MultiSelect.cjs.map +1 -1
  197. package/dist/components/MultiSelect/MultiSelect.js.map +1 -1
  198. package/dist/components/NProgress/NProgress.cjs.map +1 -1
  199. package/dist/components/Navbar/Navbar.cjs.map +1 -1
  200. package/dist/components/Navbar/Navbar.js.map +1 -1
  201. package/dist/components/NavigationMenu/NavigationMenu.cjs.map +1 -1
  202. package/dist/components/NavigationMenu/NavigationMenu.js.map +1 -1
  203. package/dist/components/NavigationRail/NavigationRail.cjs.map +1 -1
  204. package/dist/components/NavigationRail/NavigationRail.js.map +1 -1
  205. package/dist/components/NotificationCenter/NotificationCenter.cjs.map +1 -1
  206. package/dist/components/NotificationCenter/NotificationCenter.js.map +1 -1
  207. package/dist/components/NotificationCenter/use-notification-inbox.cjs.map +1 -1
  208. package/dist/components/OfflineIndicator/OfflineIndicator.cjs.map +1 -1
  209. package/dist/components/OfflineIndicator/OfflineIndicator.js.map +1 -1
  210. package/dist/components/Page/Page.cjs.map +1 -1
  211. package/dist/components/Page/Page.js.map +1 -1
  212. package/dist/components/Pagination/Pagination.cjs.map +1 -1
  213. package/dist/components/Pagination/Pagination.js.map +1 -1
  214. package/dist/components/PasswordInput/PasswordInput.cjs.map +1 -1
  215. package/dist/components/PasswordInput/PasswordInput.js.map +1 -1
  216. package/dist/components/PinInput/PinInput.cjs.map +1 -1
  217. package/dist/components/PinInput/PinInput.js.map +1 -1
  218. package/dist/components/Popover/Popover.cjs.map +1 -1
  219. package/dist/components/Popover/Popover.js.map +1 -1
  220. package/dist/components/Portal/Portal.cjs.map +1 -1
  221. package/dist/components/Progress/Progress.cjs.map +1 -1
  222. package/dist/components/Progress/Progress.js.map +1 -1
  223. package/dist/components/QRCode/QRCode.cjs.map +1 -1
  224. package/dist/components/QRCode/QRCode.js.map +1 -1
  225. package/dist/components/Radio/Radio.cjs.map +1 -1
  226. package/dist/components/Radio/Radio.js.map +1 -1
  227. package/dist/components/RangeSlider/RangeSlider.cjs.map +1 -1
  228. package/dist/components/RangeSlider/RangeSlider.js.map +1 -1
  229. package/dist/components/RatingStars/RatingStars.cjs.map +1 -1
  230. package/dist/components/RatingStars/RatingStars.js.map +1 -1
  231. package/dist/components/RefreshIndicator/RefreshIndicator.cjs.map +1 -1
  232. package/dist/components/RefreshIndicator/RefreshIndicator.js.map +1 -1
  233. package/dist/components/RelativeTime/RelativeTime.cjs.map +1 -1
  234. package/dist/components/RelativeTime/RelativeTime.js.map +1 -1
  235. package/dist/components/Resizable/Resizable.cjs.map +1 -1
  236. package/dist/components/Resizable/Resizable.js.map +1 -1
  237. package/dist/components/Scheduler/Scheduler.cjs.map +1 -1
  238. package/dist/components/Scheduler/Scheduler.js.map +1 -1
  239. package/dist/components/ScrollArea/ScrollArea.cjs.map +1 -1
  240. package/dist/components/SearchBar/SearchBar.cjs.map +1 -1
  241. package/dist/components/SearchBar/SearchBar.js.map +1 -1
  242. package/dist/components/SegmentedControl/SegmentedControl.cjs.map +1 -1
  243. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  244. package/dist/components/Select/Select.cjs.map +1 -1
  245. package/dist/components/Select/Select.js.map +1 -1
  246. package/dist/components/Sidebar/Sidebar.cjs.map +1 -1
  247. package/dist/components/Sidebar/Sidebar.js.map +1 -1
  248. package/dist/components/SignaturePad/SignaturePad.cjs.map +1 -1
  249. package/dist/components/SignaturePad/SignaturePad.js.map +1 -1
  250. package/dist/components/Slider/Slider.cjs.map +1 -1
  251. package/dist/components/Slider/Slider.js.map +1 -1
  252. package/dist/components/Sparkline/Sparkline.cjs.map +1 -1
  253. package/dist/components/Sparkline/Sparkline.js.map +1 -1
  254. package/dist/components/Spinner/Spinner.cjs.map +1 -1
  255. package/dist/components/Spinner/Spinner.js.map +1 -1
  256. package/dist/components/Stat/Stat.cjs.map +1 -1
  257. package/dist/components/Stat/Stat.js.map +1 -1
  258. package/dist/components/Stepper/Stepper.cjs.map +1 -1
  259. package/dist/components/Stepper/Stepper.js.map +1 -1
  260. package/dist/components/StepperInput/StepperInput.cjs.map +1 -1
  261. package/dist/components/StepperInput/StepperInput.js.map +1 -1
  262. package/dist/components/Switch/Switch.cjs.map +1 -1
  263. package/dist/components/Switch/Switch.js.map +1 -1
  264. package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs.map +1 -1
  265. package/dist/components/SyncStatusBadge/SyncStatusBadge.js.map +1 -1
  266. package/dist/components/Table/Table.cjs.map +1 -1
  267. package/dist/components/Table/Table.js.map +1 -1
  268. package/dist/components/Tabs/Tabs.cjs.map +1 -1
  269. package/dist/components/Tabs/Tabs.js.map +1 -1
  270. package/dist/components/Tag/Tag.cjs.map +1 -1
  271. package/dist/components/Tag/Tag.js.map +1 -1
  272. package/dist/components/Textarea/Textarea.cjs.map +1 -1
  273. package/dist/components/Textarea/Textarea.js.map +1 -1
  274. package/dist/components/TimePicker/TimePicker.cjs.map +1 -1
  275. package/dist/components/TimePicker/TimePicker.js.map +1 -1
  276. package/dist/components/Timeline/Timeline.cjs.map +1 -1
  277. package/dist/components/Timeline/Timeline.js.map +1 -1
  278. package/dist/components/Toast/ToastProvider.cjs.map +1 -1
  279. package/dist/components/Toast/ToastProvider.js.map +1 -1
  280. package/dist/components/Toggle/Toggle.cjs.map +1 -1
  281. package/dist/components/ToggleGroup/ToggleGroup.cjs.map +1 -1
  282. package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
  283. package/dist/components/Tooltip/Tooltip.cjs.map +1 -1
  284. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  285. package/dist/components/Tour/Tour.cjs.map +1 -1
  286. package/dist/components/Tour/Tour.js.map +1 -1
  287. package/dist/components/Transfer/Transfer.cjs.map +1 -1
  288. package/dist/components/Transfer/Transfer.js.map +1 -1
  289. package/dist/components/TreeView/TreeView.cjs +1 -1
  290. package/dist/components/TreeView/TreeView.cjs.map +1 -1
  291. package/dist/components/TreeView/TreeView.js +1 -4
  292. package/dist/components/TreeView/TreeView.js.map +1 -1
  293. package/dist/components/UpdatePrompt/UpdatePrompt.cjs.map +1 -1
  294. package/dist/components/UpdatePrompt/UpdatePrompt.js.map +1 -1
  295. package/dist/components/VirtualList/VirtualList.cjs.map +1 -1
  296. package/dist/components/VirtualList/VirtualList.js.map +1 -1
  297. package/dist/components/VirtualTable/VirtualTable.cjs.map +1 -1
  298. package/dist/components/VirtualTable/VirtualTable.js.map +1 -1
  299. package/dist/components/VisuallyHidden/VisuallyHidden.cjs.map +1 -1
  300. package/dist/components/Wizard/Wizard.cjs.map +1 -1
  301. package/dist/components/Wizard/Wizard.js.map +1 -1
  302. package/dist/data/data-provider-context.cjs.map +1 -1
  303. package/dist/data/use-resource.cjs.map +1 -1
  304. package/dist/editor/RichTextEditor.cjs.map +1 -1
  305. package/dist/editor/RichTextEditor.js.map +1 -1
  306. package/dist/error-boundary/use-error-handler.cjs.map +1 -1
  307. package/dist/feature-flags/FeatureFlagsProvider.cjs.map +1 -1
  308. package/dist/forms/FormField.cjs.map +1 -1
  309. package/dist/forms/masked-inputs.cjs +1 -1
  310. package/dist/forms/masked-inputs.cjs.map +1 -1
  311. package/dist/forms/masked-inputs.js +1 -1
  312. package/dist/forms/masked-inputs.js.map +1 -1
  313. package/dist/forms/use-viacep.cjs.map +1 -1
  314. package/dist/forms/use-zod-form.cjs.map +1 -1
  315. package/dist/forms/zod-resolver.cjs.map +1 -1
  316. package/dist/forms/zod-resolver.js.map +1 -1
  317. package/dist/geo/TrajectoryMap.cjs.map +1 -1
  318. package/dist/geo/TrajectoryMap.js.map +1 -1
  319. package/dist/geo/leaflet-map.cjs.map +1 -1
  320. package/dist/geo/leaflet-map.js.map +1 -1
  321. package/dist/geo/use-position-tracker.cjs.map +1 -1
  322. package/dist/hooks/use-announce.cjs.map +1 -1
  323. package/dist/hooks/use-async.cjs.map +1 -1
  324. package/dist/hooks/use-before-install-prompt.cjs.map +1 -1
  325. package/dist/hooks/use-breakpoint.cjs.map +1 -1
  326. package/dist/hooks/use-click-outside.cjs.map +1 -1
  327. package/dist/hooks/use-client-filter.cjs.map +1 -1
  328. package/dist/hooks/use-clipboard.cjs.map +1 -1
  329. package/dist/hooks/use-counter.cjs.map +1 -1
  330. package/dist/hooks/use-debounce.cjs.map +1 -1
  331. package/dist/hooks/use-deep-memo.cjs.map +1 -1
  332. package/dist/hooks/use-disclosure.cjs.map +1 -1
  333. package/dist/hooks/use-document-visibility.cjs.map +1 -1
  334. package/dist/hooks/use-event-listener.cjs.map +1 -1
  335. package/dist/hooks/use-geolocation.cjs.map +1 -1
  336. package/dist/hooks/use-hover.cjs.map +1 -1
  337. package/dist/hooks/use-idle.cjs.map +1 -1
  338. package/dist/hooks/use-install-prompt.cjs +1 -1
  339. package/dist/hooks/use-install-prompt.cjs.map +1 -1
  340. package/dist/hooks/use-install-prompt.js +1 -1
  341. package/dist/hooks/use-install-prompt.js.map +1 -1
  342. package/dist/hooks/use-intersection-observer.cjs.map +1 -1
  343. package/dist/hooks/use-interval.cjs.map +1 -1
  344. package/dist/hooks/use-is-first-render.cjs.map +1 -1
  345. package/dist/hooks/use-keyboard-shortcut.cjs +1 -1
  346. package/dist/hooks/use-keyboard-shortcut.cjs.map +1 -1
  347. package/dist/hooks/use-keyboard-shortcut.js +1 -1
  348. package/dist/hooks/use-keyboard-shortcut.js.map +1 -1
  349. package/dist/hooks/use-list-state.cjs.map +1 -1
  350. package/dist/hooks/use-local-storage.cjs.map +1 -1
  351. package/dist/hooks/use-long-press-handlers.cjs.map +1 -1
  352. package/dist/hooks/use-long-press.cjs.map +1 -1
  353. package/dist/hooks/use-map.cjs.map +1 -1
  354. package/dist/hooks/use-media-devices.cjs.map +1 -1
  355. package/dist/hooks/use-media-permission.cjs.map +1 -1
  356. package/dist/hooks/use-media-query.cjs.map +1 -1
  357. package/dist/hooks/use-object-url.cjs.map +1 -1
  358. package/dist/hooks/use-online.cjs.map +1 -1
  359. package/dist/hooks/use-pagination.cjs.map +1 -1
  360. package/dist/hooks/use-previous.cjs.map +1 -1
  361. package/dist/hooks/use-queue.cjs.map +1 -1
  362. package/dist/hooks/use-resize-observer.cjs.map +1 -1
  363. package/dist/hooks/use-scroll-overflow.cjs.map +1 -1
  364. package/dist/hooks/use-service-worker-update.cjs.map +1 -1
  365. package/dist/hooks/use-set.cjs.map +1 -1
  366. package/dist/hooks/use-sortable.cjs +1 -1
  367. package/dist/hooks/use-sortable.cjs.map +1 -1
  368. package/dist/hooks/use-sortable.js +0 -2
  369. package/dist/hooks/use-sortable.js.map +1 -1
  370. package/dist/hooks/use-stable-callback.cjs.map +1 -1
  371. package/dist/hooks/use-storage-estimate.cjs.map +1 -1
  372. package/dist/hooks/use-throttle.cjs.map +1 -1
  373. package/dist/hooks/use-timeout.cjs.map +1 -1
  374. package/dist/hooks/use-toggle.cjs.map +1 -1
  375. package/dist/hooks/use-window-size.cjs.map +1 -1
  376. package/dist/http/api-client.cjs +1 -1
  377. package/dist/http/api-client.cjs.map +1 -1
  378. package/dist/http/api-client.js +7 -5
  379. package/dist/http/api-client.js.map +1 -1
  380. package/dist/http/resumable-upload.cjs +1 -1
  381. package/dist/http/resumable-upload.cjs.map +1 -1
  382. package/dist/http/resumable-upload.js +1 -1
  383. package/dist/http/resumable-upload.js.map +1 -1
  384. package/dist/http/use-poll.cjs.map +1 -1
  385. package/dist/i18n/I18nProvider.cjs.map +1 -1
  386. package/dist/icons/Icon.cjs.map +1 -1
  387. package/dist/icons/IconProvider.cjs.map +1 -1
  388. package/dist/icons/icon-context.cjs.map +1 -1
  389. package/dist/icons/use-icon.cjs.map +1 -1
  390. package/dist/imaging/use-image-processing.cjs.map +1 -1
  391. package/dist/oauth/GoogleSignIn.cjs.map +1 -1
  392. package/dist/oauth/GoogleSignIn.js.map +1 -1
  393. package/dist/oauth/use-oauth-callback.cjs.map +1 -1
  394. package/dist/offline/use-offline-sync.cjs.map +1 -1
  395. package/dist/push/use-push-subscription.cjs.map +1 -1
  396. package/dist/query/QueryProvider.cjs.map +1 -1
  397. package/dist/query/constants.cjs +1 -1
  398. package/dist/query/constants.cjs.map +1 -1
  399. package/dist/query/constants.js +10 -10
  400. package/dist/query/constants.js.map +1 -1
  401. package/dist/query/create-query-keys.cjs +1 -1
  402. package/dist/query/create-query-keys.cjs.map +1 -1
  403. package/dist/query/create-query-keys.js +1 -1
  404. package/dist/query/create-query-keys.js.map +1 -1
  405. package/dist/query/offline-persistence.cjs.map +1 -1
  406. package/dist/query/use-cursor-query.cjs.map +1 -1
  407. package/dist/query/use-offline-mutation.cjs.map +1 -1
  408. package/dist/query/use-paginated-query.cjs.map +1 -1
  409. package/dist/router/AppRouter.cjs +1 -1
  410. package/dist/router/AppRouter.cjs.map +1 -1
  411. package/dist/router/AppRouter.js +7 -2
  412. package/dist/router/AppRouter.js.map +1 -1
  413. package/dist/sse/use-event-stream.cjs.map +1 -1
  414. package/dist/store/create-store.cjs.map +1 -1
  415. package/dist/tabular/use-tabular-predictor.cjs.map +1 -1
  416. package/dist/telemetry/TelemetryProvider.cjs.map +1 -1
  417. package/dist/tempest-react-sdk.d.ts +25 -26
  418. package/dist/theme/ThemeProvider.cjs.map +1 -1
  419. package/dist/theme/color.cjs +1 -1
  420. package/dist/theme/color.cjs.map +1 -1
  421. package/dist/theme/color.js +1 -1
  422. package/dist/theme/color.js.map +1 -1
  423. package/dist/utils/cn.cjs +1 -1
  424. package/dist/utils/cn.cjs.map +1 -1
  425. package/dist/utils/cn.js +1 -1
  426. package/dist/utils/cn.js.map +1 -1
  427. package/dist/utils/objects.cjs +1 -1
  428. package/dist/utils/objects.cjs.map +1 -1
  429. package/dist/utils/objects.js +1 -1
  430. package/dist/utils/objects.js.map +1 -1
  431. package/dist/utils/xlsx.cjs +1 -1
  432. package/dist/utils/xlsx.cjs.map +1 -1
  433. package/dist/utils/xlsx.js +3 -3
  434. package/dist/utils/xlsx.js.map +1 -1
  435. package/dist/vision/core/exceptions.cjs.map +1 -1
  436. package/dist/vision/core/exceptions.js.map +1 -1
  437. package/dist/vision/core/metadata.cjs +1 -1
  438. package/dist/vision/core/metadata.cjs.map +1 -1
  439. package/dist/vision/core/metadata.js +1 -1
  440. package/dist/vision/core/metadata.js.map +1 -1
  441. package/dist/vision/io/image.cjs +1 -1
  442. package/dist/vision/io/image.cjs.map +1 -1
  443. package/dist/vision/io/image.js +4 -2
  444. package/dist/vision/io/image.js.map +1 -1
  445. package/dist/vision/preprocess/image.cjs +1 -1
  446. package/dist/vision/preprocess/image.cjs.map +1 -1
  447. package/dist/vision/preprocess/image.js +4 -2
  448. package/dist/vision/preprocess/image.js.map +1 -1
  449. package/dist/vision/tasks/base.cjs +1 -1
  450. package/dist/vision/tasks/base.cjs.map +1 -1
  451. package/dist/vision/tasks/base.js +3 -1
  452. package/dist/vision/tasks/base.js.map +1 -1
  453. package/dist/vision/tasks/classifier.cjs +1 -1
  454. package/dist/vision/tasks/classifier.cjs.map +1 -1
  455. package/dist/vision/tasks/classifier.js +2 -2
  456. package/dist/vision/tasks/classifier.js.map +1 -1
  457. package/dist/vision/tasks/detectClassify.cjs +1 -1
  458. package/dist/vision/tasks/detectClassify.cjs.map +1 -1
  459. package/dist/vision/tasks/detectClassify.js +16 -15
  460. package/dist/vision/tasks/detectClassify.js.map +1 -1
  461. package/dist/vision/use-camera-stream.cjs.map +1 -1
  462. package/dist/vision/use-live-luminance.cjs.map +1 -1
  463. package/dist/vite/create-vite-config.cjs +1 -1
  464. package/dist/vite/create-vite-config.cjs.map +1 -1
  465. package/dist/vite/create-vite-config.js +3 -3
  466. package/dist/vite/create-vite-config.js.map +1 -1
  467. package/dist/vite/tempest-icons.cjs.map +1 -1
  468. package/dist/vite/tempest-pwa-dev-sw.cjs.map +1 -1
  469. package/dist/vite/tempest-pwa-icons.cjs.map +1 -1
  470. package/dist/ws/use-web-socket.cjs +1 -1
  471. package/dist/ws/use-web-socket.cjs.map +1 -1
  472. package/dist/ws/use-web-socket.js +5 -3
  473. package/dist/ws/use-web-socket.js.map +1 -1
  474. package/package.json +2 -2
  475. package/template/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","names":[],"sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import { forwardRef, useId } from \"react\";\nimport type { SelectHTMLAttributes } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Select.module.css\";\n\nexport interface SelectOption {\n value: string | number;\n label: string;\n disabled?: boolean;\n}\n\nexport interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {\n label?: string;\n helperText?: string;\n error?: string;\n options?: SelectOption[];\n placeholder?: string;\n wrapperClassName?: string;\n}\n\n/**\n * Native `<select>` wrapper with label/helper/error slots. Either provide\n * `options` for a quick render, or pass `<option>` children directly.\n */\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select(\n {\n label,\n helperText,\n error,\n options,\n placeholder,\n wrapperClassName,\n className,\n children,\n id,\n required,\n ...props\n },\n ref,\n) {\n const generatedId = useId();\n const selectId = id ?? generatedId;\n\n return (\n <div className={cn(styles.wrapper, error && styles.error, wrapperClassName)}>\n {label && (\n <label htmlFor={selectId} className={styles.label}>\n {label}\n {required && <span className={styles.required}>*</span>}\n </label>\n )}\n <div className={styles.field}>\n <select\n ref={ref}\n id={selectId}\n aria-invalid={!!error}\n required={required}\n className={cn(styles.select, className)}\n {...props}\n >\n {placeholder && (\n <option value=\"\" disabled hidden>\n {placeholder}\n </option>\n )}\n {options?.map((opt) => (\n <option key={opt.value} value={opt.value} disabled={opt.disabled}>\n {opt.label}\n </option>\n ))}\n {children}\n </select>\n <span className={styles.caret} aria-hidden>\n <CaretIcon />\n </span>\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helper}>{helperText}</span>\n ) : null}\n </div>\n );\n});\n\nfunction CaretIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\">\n <path\n d=\"M6 9l6 6 6-6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n"],"mappings":";;;;;AAwBA,IAAa,IAAS,EAA2C,SAC7D,EACI,UACA,eACA,UACA,YACA,gBACA,qBACA,cACA,aACA,OACA,aACA,GAAG,KAEP,GACF;CACE,IAAM,IAAc,EAAM,GACpB,IAAW,KAAM;CAEvB,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,KAAS,EAAO,OAAO,CAAgB;YAA1E;GACK,KACG,kBAAC,SAAD;IAAO,SAAS;IAAU,WAAW,EAAO;cAA5C,CACK,GACA,KAAY,kBAAC,QAAD;KAAM,WAAW,EAAO;eAAU;IAAO,CAAA,CACnD;;GAEX,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB,CACI,kBAAC,UAAD;KACS;KACL,IAAI;KACJ,gBAAc,CAAC,CAAC;KACN;KACV,WAAW,EAAG,EAAO,QAAQ,CAAS;KACtC,GAAI;eANR;MAQK,KACG,kBAAC,UAAD;OAAQ,OAAM;OAAG,UAAA;OAAS,QAAA;iBACrB;MACG,CAAA;MAEX,GAAS,KAAK,MACX,kBAAC,UAAD;OAAwB,OAAO,EAAI;OAAO,UAAU,EAAI;iBACnD,EAAI;MACD,GAFK,EAAI,KAET,CACX;MACA;KACG;QACR,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAO,eAAA;eAC3B,kBAAC,GAAD,CAAY,CAAA;IACV,CAAA,CACL;;GACJ,IACG,kBAAC,QAAD;IAAM,WAAW,EAAO;cAAY;GAAY,CAAA,IAChD,IACA,kBAAC,QAAD;IAAM,WAAW,EAAO;cAAS;GAAiB,CAAA,IAClD;EACH;;AAEb,CAAC;AAED,SAAS,IAAY;CACjB,OACI,kBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;YACjD,kBAAC,QAAD;GACI,GAAE;GACF,QAAO;GACP,aAAY;GACZ,eAAc;GACd,gBAAe;EAClB,CAAA;CACA,CAAA;AAEb"}
1
+ {"version":3,"file":"Select.js","names":[],"sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import { forwardRef, useId } from \"react\";\nimport type { SelectHTMLAttributes } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Select.module.css\";\n\nexport interface SelectOption {\n value: string | number;\n label: string;\n disabled?: boolean;\n}\n\nexport interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {\n label?: string;\n helperText?: string;\n error?: string;\n options?: SelectOption[];\n placeholder?: string;\n wrapperClassName?: string;\n}\n\n/**\n * Native `<select>` wrapper with label/helper/error slots. Either provide\n * `options` for a quick render, or pass `<option>` children directly.\n */\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select(\n {\n label,\n helperText,\n error,\n options,\n placeholder,\n wrapperClassName,\n className,\n children,\n id,\n required,\n ...props\n },\n ref,\n) {\n const generatedId = useId();\n const selectId = id ?? generatedId;\n\n return (\n <div className={cn(styles.wrapper, error && styles.error, wrapperClassName)}>\n {label && (\n <label htmlFor={selectId} className={styles.label}>\n {label}\n {required && <span className={styles.required}>*</span>}\n </label>\n )}\n <div className={styles.field}>\n <select\n ref={ref}\n id={selectId}\n aria-invalid={!!error}\n required={required}\n className={cn(styles.select, className)}\n {...props}\n >\n {placeholder && (\n <option value=\"\" disabled hidden>\n {placeholder}\n </option>\n )}\n {options?.map((opt) => (\n <option key={opt.value} value={opt.value} disabled={opt.disabled}>\n {opt.label}\n </option>\n ))}\n {children}\n </select>\n <span className={styles.caret} aria-hidden>\n <CaretIcon />\n </span>\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helper}>{helperText}</span>\n ) : null}\n </div>\n );\n});\n\nfunction CaretIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\">\n <path\n d=\"M6 9l6 6 6-6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n"],"mappings":";;;;;AAwBA,IAAa,IAAS,EAA2C,SAC7D,EACI,UACA,eACA,UACA,YACA,gBACA,qBACA,cACA,aACA,OACA,aACA,GAAG,KAEP,GACF;CACE,IAAM,IAAc,EAAM,GACpB,IAAW,KAAM;CAEvB,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,KAAS,EAAO,OAAO,CAAgB;EAA1E,UAAA;GACK,KACG,kBAAC,SAAD;IAAO,SAAS;IAAU,WAAW,EAAO;IAA5C,UAAA,CACK,GACA,KAAY,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAU,UAAA;IAAO,CAAA,CACnD;;GAEX,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAvB,UAAA,CACI,kBAAC,UAAD;KACS;KACL,IAAI;KACJ,gBAAc,CAAC,CAAC;KACN;KACV,WAAW,EAAG,EAAO,QAAQ,CAAS;KACtC,GAAI;KANR,UAAA;MAQK,KACG,kBAAC,UAAD;OAAQ,OAAM;OAAG,UAAA;OAAS,QAAA;OACrB,UAAA;MACG,CAAA;MAEX,GAAS,KAAK,MACX,kBAAC,UAAD;OAAwB,OAAO,EAAI;OAAO,UAAU,EAAI;OACnD,UAAA,EAAI;MACD,GAFK,EAAI,KAET,CACX;MACA;KACG;IACR,CAAA,GAAA,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAO,eAAA;KAC3B,UAAA,kBAAC,GAAD,CAAY,CAAA;IACV,CAAA,CACL;;GACJ,IACG,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAY,UAAA;GAAY,CAAA,IAChD,IACA,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAS,UAAA;GAAiB,CAAA,IAClD;EACH;;AAEb,CAAC;AAED,SAAS,IAAY;CACjB,OACI,kBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;EACjD,UAAA,kBAAC,QAAD;GACI,GAAE;GACF,QAAO;GACP,aAAY;GACZ,eAAc;GACd,gBAAe;EAClB,CAAA;CACA,CAAA;AAEb"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.cjs","names":[],"sources":["../../../src/components/Sidebar/Sidebar.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — header, items, footer are the three regions,\n * value/onChange the selection, and collapsed/width/collapsedWidth the two layout\n * modes it switches between.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Sidebar.module.css\";\n\nexport interface SidebarItem {\n key: string;\n label: ReactNode;\n icon?: ReactNode;\n badge?: ReactNode;\n disabled?: boolean;\n href?: string;\n}\n\nexport interface SidebarProps extends Omit<HTMLAttributes<HTMLElement>, \"onChange\"> {\n /** Top slot — typically the logo + brand. */\n header?: ReactNode;\n /** Navigation items. */\n items: SidebarItem[];\n /** Active item key. */\n value?: string;\n /** Fires when an item is clicked. Receives the item's `key`. */\n onChange?: (key: string) => void;\n /** Bottom slot — typically settings/profile/logout. */\n footer?: ReactNode;\n /** Collapsed mode — only icons visible. Default `false`. */\n collapsed?: boolean;\n /** Width when expanded, in pixels or any CSS length. Default `240px`. */\n width?: number | string;\n /** Width when collapsed, in pixels or any CSS length. Default `64px`. */\n collapsedWidth?: number | string;\n}\n\n/**\n * Desktop sidebar navigation. Pair with `<Show above=\"md\">` and a `Drawer`\n * for mobile.\n *\n * @example\n * const [tab, setTab] = useState(\"home\");\n * <Show above=\"md\">\n * <Sidebar\n * header={<Brand />}\n * items={[{ key: \"home\", label: \"Home\", icon: <Home /> }]}\n * value={tab}\n * onChange={setTab}\n * />\n * </Show>\n */\nexport function Sidebar({\n header,\n items,\n value,\n onChange,\n footer,\n collapsed = false,\n width = 240,\n collapsedWidth = 64,\n className,\n style,\n ...props\n}: SidebarProps) {\n const finalWidth =\n typeof (collapsed ? collapsedWidth : width) === \"number\"\n ? `${collapsed ? collapsedWidth : width}px`\n : collapsed\n ? collapsedWidth\n : width;\n return (\n <aside\n className={cn(styles.sidebar, collapsed && styles.collapsed, className)}\n style={{ width: finalWidth, ...style }}\n {...props}\n >\n {header && <div className={styles.header}>{header}</div>}\n <nav className={styles.nav} aria-label=\"Navegação lateral\">\n {items.map((item) => {\n const active = item.key === value;\n return (\n <button\n key={item.key}\n type=\"button\"\n className={cn(styles.item, active && styles.active)}\n aria-current={active ? \"page\" : undefined}\n disabled={item.disabled}\n onClick={() => onChange?.(item.key)}\n title={\n collapsed && typeof item.label === \"string\" ? item.label : undefined\n }\n >\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\n {!collapsed && <span className={styles.label}>{item.label}</span>}\n {!collapsed && item.badge !== undefined && (\n <span className={styles.badge}>{item.badge}</span>\n )}\n </button>\n );\n })}\n </nav>\n {footer && <div className={styles.footer}>{footer}</div>}\n </aside>\n );\n}\n"],"mappings":"2GAoDA,SAAgB,EAAQ,CACpB,SACA,QACA,QACA,WACA,SACA,YAAY,GACZ,QAAQ,IACR,iBAAiB,GACjB,YACA,QACA,GAAG,GACU,CACb,IAAM,EACF,OAAQ,EAAY,EAAiB,IAAW,SAC1C,GAAG,EAAY,EAAiB,EAAM,IACtC,EACE,EACA,EACZ,OACI,EAAA,EAAA,KAAA,CAAC,QAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,GAAa,EAAA,QAAO,UAAW,CAAS,EACtE,MAAO,CAAE,MAAO,EAAY,GAAG,CAAM,EACrC,GAAI,WAHR,CAKK,IAAU,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,gBAAS,CAAY,CAAA,GACvD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,IAAK,aAAW,6BAClC,EAAM,IAAK,GAAS,CACjB,IAAM,EAAS,EAAK,MAAQ,EAC5B,OACI,EAAA,EAAA,KAAA,CAAC,SAAD,CAEI,KAAK,SACL,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,GAAU,EAAA,QAAO,MAAM,EAClD,eAAc,EAAS,OAAS,IAAA,GAChC,SAAU,EAAK,SACf,YAAe,IAAW,EAAK,GAAG,EAClC,MACI,GAAa,OAAO,EAAK,OAAU,SAAW,EAAK,MAAQ,IAAA,YARnE,CAWK,EAAK,OAAQ,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,cAAO,EAAK,IAAW,CAAA,EAC5D,CAAC,IAAa,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,eAAQ,EAAK,KAAY,CAAA,EAC/D,CAAC,GAAa,EAAK,QAAU,IAAA,KAC1B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,eAAQ,EAAK,KAAY,CAAA,CAEjD,GAfC,EAAK,GAeN,CAEhB,CAAC,CACA,CAAA,EACJ,IAAU,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,gBAAS,CAAY,CAAA,CACpD,GAEf"}
1
+ {"version":3,"file":"Sidebar.cjs","names":[],"sources":["../../../src/components/Sidebar/Sidebar.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — header, items, footer are the three regions,\n * value/onChange the selection, and collapsed/width/collapsedWidth the two layout\n * modes it switches between.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Sidebar.module.css\";\n\nexport interface SidebarItem {\n key: string;\n label: ReactNode;\n icon?: ReactNode;\n badge?: ReactNode;\n disabled?: boolean;\n href?: string;\n}\n\nexport interface SidebarProps extends Omit<HTMLAttributes<HTMLElement>, \"onChange\"> {\n /** Top slot — typically the logo + brand. */\n header?: ReactNode;\n /** Navigation items. */\n items: SidebarItem[];\n /** Active item key. */\n value?: string;\n /** Fires when an item is clicked. Receives the item's `key`. */\n onChange?: (key: string) => void;\n /** Bottom slot — typically settings/profile/logout. */\n footer?: ReactNode;\n /** Collapsed mode — only icons visible. Default `false`. */\n collapsed?: boolean;\n /** Width when expanded, in pixels or any CSS length. Default `240px`. */\n width?: number | string;\n /** Width when collapsed, in pixels or any CSS length. Default `64px`. */\n collapsedWidth?: number | string;\n}\n\n/**\n * Desktop sidebar navigation. Pair with `<Show above=\"md\">` and a `Drawer`\n * for mobile.\n *\n * @example\n * const [tab, setTab] = useState(\"home\");\n * <Show above=\"md\">\n * <Sidebar\n * header={<Brand />}\n * items={[{ key: \"home\", label: \"Home\", icon: <Home /> }]}\n * value={tab}\n * onChange={setTab}\n * />\n * </Show>\n */\nexport function Sidebar({\n header,\n items,\n value,\n onChange,\n footer,\n collapsed = false,\n width = 240,\n collapsedWidth = 64,\n className,\n style,\n ...props\n}: SidebarProps) {\n const finalWidth =\n typeof (collapsed ? collapsedWidth : width) === \"number\"\n ? `${collapsed ? collapsedWidth : width}px`\n : collapsed\n ? collapsedWidth\n : width;\n return (\n <aside\n className={cn(styles.sidebar, collapsed && styles.collapsed, className)}\n style={{ width: finalWidth, ...style }}\n {...props}\n >\n {header && <div className={styles.header}>{header}</div>}\n <nav className={styles.nav} aria-label=\"Navegação lateral\">\n {items.map((item) => {\n const active = item.key === value;\n return (\n <button\n key={item.key}\n type=\"button\"\n className={cn(styles.item, active && styles.active)}\n aria-current={active ? \"page\" : undefined}\n disabled={item.disabled}\n onClick={() => onChange?.(item.key)}\n title={\n collapsed && typeof item.label === \"string\" ? item.label : undefined\n }\n >\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\n {!collapsed && <span className={styles.label}>{item.label}</span>}\n {!collapsed && item.badge !== undefined && (\n <span className={styles.badge}>{item.badge}</span>\n )}\n </button>\n );\n })}\n </nav>\n {footer && <div className={styles.footer}>{footer}</div>}\n </aside>\n );\n}\n"],"mappings":"2GAoDA,SAAgB,EAAQ,CACpB,SACA,QACA,QACA,WACA,SACA,YAAY,GACZ,QAAQ,IACR,iBAAiB,GACjB,YACA,QACA,GAAG,GACU,CACb,IAAM,EACF,OAAQ,EAAY,EAAiB,IAAW,SAC1C,GAAG,EAAY,EAAiB,EAAM,IACtC,EACE,EACA,EACZ,OACI,EAAA,EAAA,KAAA,CAAC,QAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,GAAa,EAAA,QAAO,UAAW,CAAS,EACtE,MAAO,CAAE,MAAO,EAAY,GAAG,CAAM,EACrC,GAAI,EAHR,SAAA,CAKK,IAAU,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,OAAS,SAAA,CAAY,CAAA,GACvD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,IAAK,aAAW,oBAClC,SAAA,EAAM,IAAK,GAAS,CACjB,IAAM,EAAS,EAAK,MAAQ,EAC5B,OACI,EAAA,EAAA,KAAA,CAAC,SAAD,CAEI,KAAK,SACL,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,GAAU,EAAA,QAAO,MAAM,EAClD,eAAc,EAAS,OAAS,IAAA,GAChC,SAAU,EAAK,SACf,YAAe,IAAW,EAAK,GAAG,EAClC,MACI,GAAa,OAAO,EAAK,OAAU,SAAW,EAAK,MAAQ,IAAA,GARnE,SAAA,CAWK,EAAK,OAAQ,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,KAAO,SAAA,EAAK,IAAW,CAAA,EAC5D,CAAC,IAAa,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,EAAK,KAAY,CAAA,EAC/D,CAAC,GAAa,EAAK,QAAU,IAAA,KAC1B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,EAAK,KAAY,CAAA,CAEjD,CAfC,EAAA,EAAK,GAeN,CAEhB,CAAC,CACA,CAAA,EACJ,IAAU,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,OAAS,SAAA,CAAY,CAAA,CACpD,GAEf"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.js","names":[],"sources":["../../../src/components/Sidebar/Sidebar.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — header, items, footer are the three regions,\n * value/onChange the selection, and collapsed/width/collapsedWidth the two layout\n * modes it switches between.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Sidebar.module.css\";\n\nexport interface SidebarItem {\n key: string;\n label: ReactNode;\n icon?: ReactNode;\n badge?: ReactNode;\n disabled?: boolean;\n href?: string;\n}\n\nexport interface SidebarProps extends Omit<HTMLAttributes<HTMLElement>, \"onChange\"> {\n /** Top slot — typically the logo + brand. */\n header?: ReactNode;\n /** Navigation items. */\n items: SidebarItem[];\n /** Active item key. */\n value?: string;\n /** Fires when an item is clicked. Receives the item's `key`. */\n onChange?: (key: string) => void;\n /** Bottom slot — typically settings/profile/logout. */\n footer?: ReactNode;\n /** Collapsed mode — only icons visible. Default `false`. */\n collapsed?: boolean;\n /** Width when expanded, in pixels or any CSS length. Default `240px`. */\n width?: number | string;\n /** Width when collapsed, in pixels or any CSS length. Default `64px`. */\n collapsedWidth?: number | string;\n}\n\n/**\n * Desktop sidebar navigation. Pair with `<Show above=\"md\">` and a `Drawer`\n * for mobile.\n *\n * @example\n * const [tab, setTab] = useState(\"home\");\n * <Show above=\"md\">\n * <Sidebar\n * header={<Brand />}\n * items={[{ key: \"home\", label: \"Home\", icon: <Home /> }]}\n * value={tab}\n * onChange={setTab}\n * />\n * </Show>\n */\nexport function Sidebar({\n header,\n items,\n value,\n onChange,\n footer,\n collapsed = false,\n width = 240,\n collapsedWidth = 64,\n className,\n style,\n ...props\n}: SidebarProps) {\n const finalWidth =\n typeof (collapsed ? collapsedWidth : width) === \"number\"\n ? `${collapsed ? collapsedWidth : width}px`\n : collapsed\n ? collapsedWidth\n : width;\n return (\n <aside\n className={cn(styles.sidebar, collapsed && styles.collapsed, className)}\n style={{ width: finalWidth, ...style }}\n {...props}\n >\n {header && <div className={styles.header}>{header}</div>}\n <nav className={styles.nav} aria-label=\"Navegação lateral\">\n {items.map((item) => {\n const active = item.key === value;\n return (\n <button\n key={item.key}\n type=\"button\"\n className={cn(styles.item, active && styles.active)}\n aria-current={active ? \"page\" : undefined}\n disabled={item.disabled}\n onClick={() => onChange?.(item.key)}\n title={\n collapsed && typeof item.label === \"string\" ? item.label : undefined\n }\n >\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\n {!collapsed && <span className={styles.label}>{item.label}</span>}\n {!collapsed && item.badge !== undefined && (\n <span className={styles.badge}>{item.badge}</span>\n )}\n </button>\n );\n })}\n </nav>\n {footer && <div className={styles.footer}>{footer}</div>}\n </aside>\n );\n}\n"],"mappings":";;;;AAoDA,SAAgB,EAAQ,EACpB,WACA,UACA,UACA,aACA,WACA,eAAY,IACZ,WAAQ,KACR,oBAAiB,IACjB,cACA,UACA,GAAG,KACU;CACb,IAAM,IACF,QAAQ,IAAY,IAAiB,MAAW,WAC1C,GAAG,IAAY,IAAiB,EAAM,MACtC,IACE,IACA;CACZ,OACI,kBAAC,SAAD;EACI,WAAW,EAAG,EAAO,SAAS,KAAa,EAAO,WAAW,CAAS;EACtE,OAAO;GAAE,OAAO;GAAY,GAAG;EAAM;EACrC,GAAI;YAHR;GAKK,KAAU,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAS;GAAY,CAAA;GACvD,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAK,cAAW;cAClC,EAAM,KAAK,MAAS;KACjB,IAAM,IAAS,EAAK,QAAQ;KAC5B,OACI,kBAAC,UAAD;MAEI,MAAK;MACL,WAAW,EAAG,EAAO,MAAM,KAAU,EAAO,MAAM;MAClD,gBAAc,IAAS,SAAS,KAAA;MAChC,UAAU,EAAK;MACf,eAAe,IAAW,EAAK,GAAG;MAClC,OACI,KAAa,OAAO,EAAK,SAAU,WAAW,EAAK,QAAQ,KAAA;gBARnE;OAWK,EAAK,QAAQ,kBAAC,QAAD;QAAM,WAAW,EAAO;kBAAO,EAAK;OAAW,CAAA;OAC5D,CAAC,KAAa,kBAAC,QAAD;QAAM,WAAW,EAAO;kBAAQ,EAAK;OAAY,CAAA;OAC/D,CAAC,KAAa,EAAK,UAAU,KAAA,KAC1B,kBAAC,QAAD;QAAM,WAAW,EAAO;kBAAQ,EAAK;OAAY,CAAA;MAEjD;QAfC,EAAK,GAeN;IAEhB,CAAC;GACA,CAAA;GACJ,KAAU,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAS;GAAY,CAAA;EACpD;;AAEf"}
1
+ {"version":3,"file":"Sidebar.js","names":[],"sources":["../../../src/components/Sidebar/Sidebar.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — header, items, footer are the three regions,\n * value/onChange the selection, and collapsed/width/collapsedWidth the two layout\n * modes it switches between.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Sidebar.module.css\";\n\nexport interface SidebarItem {\n key: string;\n label: ReactNode;\n icon?: ReactNode;\n badge?: ReactNode;\n disabled?: boolean;\n href?: string;\n}\n\nexport interface SidebarProps extends Omit<HTMLAttributes<HTMLElement>, \"onChange\"> {\n /** Top slot — typically the logo + brand. */\n header?: ReactNode;\n /** Navigation items. */\n items: SidebarItem[];\n /** Active item key. */\n value?: string;\n /** Fires when an item is clicked. Receives the item's `key`. */\n onChange?: (key: string) => void;\n /** Bottom slot — typically settings/profile/logout. */\n footer?: ReactNode;\n /** Collapsed mode — only icons visible. Default `false`. */\n collapsed?: boolean;\n /** Width when expanded, in pixels or any CSS length. Default `240px`. */\n width?: number | string;\n /** Width when collapsed, in pixels or any CSS length. Default `64px`. */\n collapsedWidth?: number | string;\n}\n\n/**\n * Desktop sidebar navigation. Pair with `<Show above=\"md\">` and a `Drawer`\n * for mobile.\n *\n * @example\n * const [tab, setTab] = useState(\"home\");\n * <Show above=\"md\">\n * <Sidebar\n * header={<Brand />}\n * items={[{ key: \"home\", label: \"Home\", icon: <Home /> }]}\n * value={tab}\n * onChange={setTab}\n * />\n * </Show>\n */\nexport function Sidebar({\n header,\n items,\n value,\n onChange,\n footer,\n collapsed = false,\n width = 240,\n collapsedWidth = 64,\n className,\n style,\n ...props\n}: SidebarProps) {\n const finalWidth =\n typeof (collapsed ? collapsedWidth : width) === \"number\"\n ? `${collapsed ? collapsedWidth : width}px`\n : collapsed\n ? collapsedWidth\n : width;\n return (\n <aside\n className={cn(styles.sidebar, collapsed && styles.collapsed, className)}\n style={{ width: finalWidth, ...style }}\n {...props}\n >\n {header && <div className={styles.header}>{header}</div>}\n <nav className={styles.nav} aria-label=\"Navegação lateral\">\n {items.map((item) => {\n const active = item.key === value;\n return (\n <button\n key={item.key}\n type=\"button\"\n className={cn(styles.item, active && styles.active)}\n aria-current={active ? \"page\" : undefined}\n disabled={item.disabled}\n onClick={() => onChange?.(item.key)}\n title={\n collapsed && typeof item.label === \"string\" ? item.label : undefined\n }\n >\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\n {!collapsed && <span className={styles.label}>{item.label}</span>}\n {!collapsed && item.badge !== undefined && (\n <span className={styles.badge}>{item.badge}</span>\n )}\n </button>\n );\n })}\n </nav>\n {footer && <div className={styles.footer}>{footer}</div>}\n </aside>\n );\n}\n"],"mappings":";;;;AAoDA,SAAgB,EAAQ,EACpB,WACA,UACA,UACA,aACA,WACA,eAAY,IACZ,WAAQ,KACR,oBAAiB,IACjB,cACA,UACA,GAAG,KACU;CACb,IAAM,IACF,QAAQ,IAAY,IAAiB,MAAW,WAC1C,GAAG,IAAY,IAAiB,EAAM,MACtC,IACE,IACA;CACZ,OACI,kBAAC,SAAD;EACI,WAAW,EAAG,EAAO,SAAS,KAAa,EAAO,WAAW,CAAS;EACtE,OAAO;GAAE,OAAO;GAAY,GAAG;EAAM;EACrC,GAAI;EAHR,UAAA;GAKK,KAAU,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAS,UAAA;GAAY,CAAA;GACvD,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAK,cAAW;IAClC,UAAA,EAAM,KAAK,MAAS;KACjB,IAAM,IAAS,EAAK,QAAQ;KAC5B,OACI,kBAAC,UAAD;MAEI,MAAK;MACL,WAAW,EAAG,EAAO,MAAM,KAAU,EAAO,MAAM;MAClD,gBAAc,IAAS,SAAS,KAAA;MAChC,UAAU,EAAK;MACf,eAAe,IAAW,EAAK,GAAG;MAClC,OACI,KAAa,OAAO,EAAK,SAAU,WAAW,EAAK,QAAQ,KAAA;MARnE,UAAA;OAWK,EAAK,QAAQ,kBAAC,QAAD;QAAM,WAAW,EAAO;QAAO,UAAA,EAAK;OAAW,CAAA;OAC5D,CAAC,KAAa,kBAAC,QAAD;QAAM,WAAW,EAAO;QAAQ,UAAA,EAAK;OAAY,CAAA;OAC/D,CAAC,KAAa,EAAK,UAAU,KAAA,KAC1B,kBAAC,QAAD;QAAM,WAAW,EAAO;QAAQ,UAAA,EAAK;OAAY,CAAA;MAEjD;KAfC,GAAA,EAAK,GAeN;IAEhB,CAAC;GACA,CAAA;GACJ,KAAU,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAS,UAAA;GAAY,CAAA;EACpD;;AAEf"}
@@ -1 +1 @@
1
- {"version":3,"file":"SignaturePad.cjs","names":[],"sources":["../../../src/components/SignaturePad/SignaturePad.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count, function-lines — the canvas (width,\n * height, penColor, penWidth), the lifecycle an app needs to enable its save button\n * (onBegin, onEnd, onEmptyChange) and the built-in actions with their copy\n * (showActions, clearLabel, undoLabel, label). The body is the stroke buffer plus\n * undo history, which are the same array.\n */\nimport { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport type { PointerEvent as ReactPointerEvent } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { Button } from \"../Button\";\nimport styles from \"./SignaturePad.module.css\";\n\n/** A single sampled point of a stroke, in CSS pixels relative to the canvas. */\ninterface Point {\n x: number;\n y: number;\n}\n\n/** Imperative handle exposed through `ref`. */\nexport interface SignaturePadHandle {\n /** Drop every stroke. */\n clear: () => void;\n /** Drop the last stroke. */\n undo: () => void;\n /** `true` while nothing has been drawn. */\n isEmpty: () => boolean;\n /** Export as a data URL. Returns `\"\"` when the canvas is unavailable. */\n toDataURL: (type?: string, quality?: number) => string;\n /** Export as a `Blob` — what you actually upload. `null` when unavailable. */\n toBlob: (type?: string, quality?: number) => Promise<Blob | null>;\n}\n\nexport interface SignaturePadProps {\n /** Drawing surface width in CSS pixels. Default `400`. */\n width?: number;\n /** Drawing surface height in CSS pixels. Default `160`. */\n height?: number;\n /**\n * Stroke color. Defaults to the canvas' computed `color`, which the\n * stylesheet binds to `--tempest-text` — so the signature follows the theme\n * (including dark mode) instead of being hardcoded black.\n */\n penColor?: string;\n /** Stroke width in CSS pixels. Default `2`. */\n penWidth?: number;\n /** Blocks drawing and dims the surface. */\n disabled?: boolean;\n /** Accessible name of the surface. Default `\"Signature\"`. */\n label?: string;\n /** Called on the first move of each stroke. */\n onBegin?: () => void;\n /** Called when a stroke ends, with the current image as a data URL. */\n onEnd?: (dataUrl: string) => void;\n /** Called whenever the emptiness changes — wire it to a submit button. */\n onEmptyChange?: (isEmpty: boolean) => void;\n /** Renders the Clear/Undo buttons. Default `true`. */\n showActions?: boolean;\n clearLabel?: string;\n undoLabel?: string;\n className?: string;\n}\n\n/**\n * Signature capture on a canvas — the \"sign here\" field of a delivery receipt,\n * a service order, a term of acceptance.\n *\n * Strokes are kept as point lists and the canvas is **redrawn** from them, which\n * is what makes `undo` possible at all: a canvas holds pixels, not history, so\n * removing the last stroke means replaying the rest.\n *\n * The backing store is scaled by `devicePixelRatio`, so the line is crisp on a\n * phone instead of the blurry 1x bitmap a naive canvas produces.\n *\n * @example\n * ```tsx\n * const pad = useRef<SignaturePadHandle>(null);\n * const [empty, setEmpty] = useState(true);\n *\n * async function submit() {\n * const blob = await pad.current?.toBlob(\"image/png\");\n * if (blob) await api.upload(\"/receipts/42/signature\", blob);\n * }\n *\n * <SignaturePad ref={pad} label=\"Assinatura do cliente\" onEmptyChange={setEmpty} />\n * <Button disabled={empty} onClick={submit}>Enviar</Button>\n * ```\n */\nexport const SignaturePad = forwardRef<SignaturePadHandle, SignaturePadProps>(function SignaturePad(\n {\n width = 400,\n height = 160,\n penColor,\n penWidth = 2,\n disabled = false,\n label = \"Signature\",\n onBegin,\n onEnd,\n onEmptyChange,\n showActions = true,\n clearLabel = \"Clear\",\n undoLabel = \"Undo\",\n className,\n },\n ref,\n) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const strokesRef = useRef<Point[][]>([]);\n const drawingRef = useRef(false);\n const [isEmpty, setIsEmpty] = useState(true);\n\n const resolvePenColor = useCallback((): string => {\n if (penColor) return penColor;\n const canvas = canvasRef.current;\n if (!canvas || typeof window === \"undefined\") return \"#101828\";\n return window.getComputedStyle(canvas).color || \"#101828\";\n }, [penColor]);\n\n /**\n * Repaint the whole surface from the stroke list, honouring the pixel ratio.\n *\n * A one-point stroke (a tap) gets a line back to its own origin: `stroke()`\n * over a path with a single point paints nothing, so without it a tap would\n * silently produce no dot while still counting as \"not empty\".\n */\n const redraw = useCallback((): void => {\n const canvas = canvasRef.current;\n const context = canvas?.getContext(\"2d\");\n if (!canvas || !context) return;\n\n const ratio = typeof window === \"undefined\" ? 1 : window.devicePixelRatio || 1;\n canvas.width = width * ratio;\n canvas.height = height * ratio;\n context.setTransform(ratio, 0, 0, ratio, 0, 0);\n context.clearRect(0, 0, width, height);\n\n context.lineWidth = penWidth;\n context.lineCap = \"round\";\n context.lineJoin = \"round\";\n context.strokeStyle = resolvePenColor();\n\n for (const stroke of strokesRef.current) {\n if (stroke.length === 0) continue;\n context.beginPath();\n context.moveTo(stroke[0].x, stroke[0].y);\n for (const point of stroke.slice(1)) {\n context.lineTo(point.x, point.y);\n }\n if (stroke.length === 1) context.lineTo(stroke[0].x, stroke[0].y);\n context.stroke();\n }\n }, [height, penWidth, resolvePenColor, width]);\n\n useEffect(() => {\n redraw();\n }, [redraw]);\n\n const setEmptiness = useCallback(\n (next: boolean): void => {\n setIsEmpty((current) => {\n if (current !== next) onEmptyChange?.(next);\n return next;\n });\n },\n [onEmptyChange],\n );\n\n const pointFrom = useCallback((event: ReactPointerEvent<HTMLCanvasElement>): Point => {\n const rect = canvasRef.current?.getBoundingClientRect();\n return {\n x: event.clientX - (rect?.left ?? 0),\n y: event.clientY - (rect?.top ?? 0),\n };\n }, []);\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (disabled) return;\n drawingRef.current = true;\n strokesRef.current = [...strokesRef.current, [pointFrom(event)]];\n canvasRef.current?.setPointerCapture?.(event.pointerId);\n onBegin?.();\n setEmptiness(false);\n redraw();\n },\n [disabled, onBegin, pointFrom, redraw, setEmptiness],\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (!drawingRef.current || disabled) return;\n const strokes = strokesRef.current;\n strokes[strokes.length - 1].push(pointFrom(event));\n redraw();\n },\n [disabled, pointFrom, redraw],\n );\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (!drawingRef.current) return;\n drawingRef.current = false;\n canvasRef.current?.releasePointerCapture?.(event.pointerId);\n onEnd?.(canvasRef.current?.toDataURL() ?? \"\");\n },\n [onEnd],\n );\n\n const clear = useCallback((): void => {\n strokesRef.current = [];\n setEmptiness(true);\n redraw();\n }, [redraw, setEmptiness]);\n\n const undo = useCallback((): void => {\n strokesRef.current = strokesRef.current.slice(0, -1);\n setEmptiness(strokesRef.current.length === 0);\n redraw();\n }, [redraw, setEmptiness]);\n\n useImperativeHandle(\n ref,\n () => ({\n clear,\n undo,\n isEmpty: () => strokesRef.current.length === 0,\n toDataURL: (type, quality) => canvasRef.current?.toDataURL(type, quality) ?? \"\",\n toBlob: (type, quality) =>\n new Promise((resolve) => {\n const canvas = canvasRef.current;\n if (!canvas?.toBlob) {\n resolve(null);\n return;\n }\n canvas.toBlob((blob) => resolve(blob), type, quality);\n }),\n }),\n [clear, undo],\n );\n\n return (\n <div className={cn(styles.pad, disabled && styles.disabled, className)}>\n <canvas\n ref={canvasRef}\n role=\"img\"\n aria-label={label}\n aria-disabled={disabled || undefined}\n className={styles.canvas}\n style={{ width, height, touchAction: \"none\" }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerLeave={handlePointerUp}\n />\n {showActions ? (\n <div className={styles.actions}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={undo}\n disabled={disabled || isEmpty}\n >\n {undoLabel}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={clear}\n disabled={disabled || isEmpty}\n >\n {clearLabel}\n </Button>\n </div>\n ) : null}\n </div>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"SignaturePad.cjs","names":[],"sources":["../../../src/components/SignaturePad/SignaturePad.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count, function-lines — the canvas (width,\n * height, penColor, penWidth), the lifecycle an app needs to enable its save button\n * (onBegin, onEnd, onEmptyChange) and the built-in actions with their copy\n * (showActions, clearLabel, undoLabel, label). The body is the stroke buffer plus\n * undo history, which are the same array.\n */\nimport { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport type { PointerEvent as ReactPointerEvent } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { Button } from \"../Button\";\nimport styles from \"./SignaturePad.module.css\";\n\n/** A single sampled point of a stroke, in CSS pixels relative to the canvas. */\ninterface Point {\n x: number;\n y: number;\n}\n\n/** Imperative handle exposed through `ref`. */\nexport interface SignaturePadHandle {\n /** Drop every stroke. */\n clear: () => void;\n /** Drop the last stroke. */\n undo: () => void;\n /** `true` while nothing has been drawn. */\n isEmpty: () => boolean;\n /** Export as a data URL. Returns `\"\"` when the canvas is unavailable. */\n toDataURL: (type?: string, quality?: number) => string;\n /** Export as a `Blob` — what you actually upload. `null` when unavailable. */\n toBlob: (type?: string, quality?: number) => Promise<Blob | null>;\n}\n\nexport interface SignaturePadProps {\n /** Drawing surface width in CSS pixels. Default `400`. */\n width?: number;\n /** Drawing surface height in CSS pixels. Default `160`. */\n height?: number;\n /**\n * Stroke color. Defaults to the canvas' computed `color`, which the\n * stylesheet binds to `--tempest-text` — so the signature follows the theme\n * (including dark mode) instead of being hardcoded black.\n */\n penColor?: string;\n /** Stroke width in CSS pixels. Default `2`. */\n penWidth?: number;\n /** Blocks drawing and dims the surface. */\n disabled?: boolean;\n /** Accessible name of the surface. Default `\"Signature\"`. */\n label?: string;\n /** Called on the first move of each stroke. */\n onBegin?: () => void;\n /** Called when a stroke ends, with the current image as a data URL. */\n onEnd?: (dataUrl: string) => void;\n /** Called whenever the emptiness changes — wire it to a submit button. */\n onEmptyChange?: (isEmpty: boolean) => void;\n /** Renders the Clear/Undo buttons. Default `true`. */\n showActions?: boolean;\n clearLabel?: string;\n undoLabel?: string;\n className?: string;\n}\n\n/**\n * Signature capture on a canvas — the \"sign here\" field of a delivery receipt,\n * a service order, a term of acceptance.\n *\n * Strokes are kept as point lists and the canvas is **redrawn** from them, which\n * is what makes `undo` possible at all: a canvas holds pixels, not history, so\n * removing the last stroke means replaying the rest.\n *\n * The backing store is scaled by `devicePixelRatio`, so the line is crisp on a\n * phone instead of the blurry 1x bitmap a naive canvas produces.\n *\n * @example\n * ```tsx\n * const pad = useRef<SignaturePadHandle>(null);\n * const [empty, setEmpty] = useState(true);\n *\n * async function submit() {\n * const blob = await pad.current?.toBlob(\"image/png\");\n * if (blob) await api.upload(\"/receipts/42/signature\", blob);\n * }\n *\n * <SignaturePad ref={pad} label=\"Assinatura do cliente\" onEmptyChange={setEmpty} />\n * <Button disabled={empty} onClick={submit}>Enviar</Button>\n * ```\n */\nexport const SignaturePad = forwardRef<SignaturePadHandle, SignaturePadProps>(function SignaturePad(\n {\n width = 400,\n height = 160,\n penColor,\n penWidth = 2,\n disabled = false,\n label = \"Signature\",\n onBegin,\n onEnd,\n onEmptyChange,\n showActions = true,\n clearLabel = \"Clear\",\n undoLabel = \"Undo\",\n className,\n },\n ref,\n) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const strokesRef = useRef<Point[][]>([]);\n const drawingRef = useRef(false);\n const [isEmpty, setIsEmpty] = useState(true);\n\n const resolvePenColor = useCallback((): string => {\n if (penColor) return penColor;\n const canvas = canvasRef.current;\n if (!canvas || typeof window === \"undefined\") return \"#101828\";\n return window.getComputedStyle(canvas).color || \"#101828\";\n }, [penColor]);\n\n /**\n * Repaint the whole surface from the stroke list, honouring the pixel ratio.\n *\n * A one-point stroke (a tap) gets a line back to its own origin: `stroke()`\n * over a path with a single point paints nothing, so without it a tap would\n * silently produce no dot while still counting as \"not empty\".\n */\n const redraw = useCallback((): void => {\n const canvas = canvasRef.current;\n const context = canvas?.getContext(\"2d\");\n if (!canvas || !context) return;\n\n const ratio = typeof window === \"undefined\" ? 1 : window.devicePixelRatio || 1;\n canvas.width = width * ratio;\n canvas.height = height * ratio;\n context.setTransform(ratio, 0, 0, ratio, 0, 0);\n context.clearRect(0, 0, width, height);\n\n context.lineWidth = penWidth;\n context.lineCap = \"round\";\n context.lineJoin = \"round\";\n context.strokeStyle = resolvePenColor();\n\n for (const stroke of strokesRef.current) {\n if (stroke.length === 0) continue;\n context.beginPath();\n context.moveTo(stroke[0].x, stroke[0].y);\n for (const point of stroke.slice(1)) {\n context.lineTo(point.x, point.y);\n }\n if (stroke.length === 1) context.lineTo(stroke[0].x, stroke[0].y);\n context.stroke();\n }\n }, [height, penWidth, resolvePenColor, width]);\n\n useEffect(() => {\n redraw();\n }, [redraw]);\n\n const setEmptiness = useCallback(\n (next: boolean): void => {\n setIsEmpty((current) => {\n if (current !== next) onEmptyChange?.(next);\n return next;\n });\n },\n [onEmptyChange],\n );\n\n const pointFrom = useCallback((event: ReactPointerEvent<HTMLCanvasElement>): Point => {\n const rect = canvasRef.current?.getBoundingClientRect();\n return {\n x: event.clientX - (rect?.left ?? 0),\n y: event.clientY - (rect?.top ?? 0),\n };\n }, []);\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (disabled) return;\n drawingRef.current = true;\n strokesRef.current = [...strokesRef.current, [pointFrom(event)]];\n canvasRef.current?.setPointerCapture?.(event.pointerId);\n onBegin?.();\n setEmptiness(false);\n redraw();\n },\n [disabled, onBegin, pointFrom, redraw, setEmptiness],\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (!drawingRef.current || disabled) return;\n const strokes = strokesRef.current;\n strokes[strokes.length - 1].push(pointFrom(event));\n redraw();\n },\n [disabled, pointFrom, redraw],\n );\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (!drawingRef.current) return;\n drawingRef.current = false;\n canvasRef.current?.releasePointerCapture?.(event.pointerId);\n onEnd?.(canvasRef.current?.toDataURL() ?? \"\");\n },\n [onEnd],\n );\n\n const clear = useCallback((): void => {\n strokesRef.current = [];\n setEmptiness(true);\n redraw();\n }, [redraw, setEmptiness]);\n\n const undo = useCallback((): void => {\n strokesRef.current = strokesRef.current.slice(0, -1);\n setEmptiness(strokesRef.current.length === 0);\n redraw();\n }, [redraw, setEmptiness]);\n\n useImperativeHandle(\n ref,\n () => ({\n clear,\n undo,\n isEmpty: () => strokesRef.current.length === 0,\n toDataURL: (type, quality) => canvasRef.current?.toDataURL(type, quality) ?? \"\",\n toBlob: (type, quality) =>\n new Promise((resolve) => {\n const canvas = canvasRef.current;\n if (!canvas?.toBlob) {\n resolve(null);\n return;\n }\n canvas.toBlob((blob) => resolve(blob), type, quality);\n }),\n }),\n [clear, undo],\n );\n\n return (\n <div className={cn(styles.pad, disabled && styles.disabled, className)}>\n <canvas\n ref={canvasRef}\n role=\"img\"\n aria-label={label}\n aria-disabled={disabled || undefined}\n className={styles.canvas}\n style={{ width, height, touchAction: \"none\" }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerLeave={handlePointerUp}\n />\n {showActions ? (\n <div className={styles.actions}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={undo}\n disabled={disabled || isEmpty}\n >\n {undoLabel}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={clear}\n disabled={disabled || isEmpty}\n >\n {clearLabel}\n </Button>\n </div>\n ) : null}\n </div>\n );\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SignaturePad.js","names":[],"sources":["../../../src/components/SignaturePad/SignaturePad.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count, function-lines — the canvas (width,\n * height, penColor, penWidth), the lifecycle an app needs to enable its save button\n * (onBegin, onEnd, onEmptyChange) and the built-in actions with their copy\n * (showActions, clearLabel, undoLabel, label). The body is the stroke buffer plus\n * undo history, which are the same array.\n */\nimport { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport type { PointerEvent as ReactPointerEvent } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { Button } from \"../Button\";\nimport styles from \"./SignaturePad.module.css\";\n\n/** A single sampled point of a stroke, in CSS pixels relative to the canvas. */\ninterface Point {\n x: number;\n y: number;\n}\n\n/** Imperative handle exposed through `ref`. */\nexport interface SignaturePadHandle {\n /** Drop every stroke. */\n clear: () => void;\n /** Drop the last stroke. */\n undo: () => void;\n /** `true` while nothing has been drawn. */\n isEmpty: () => boolean;\n /** Export as a data URL. Returns `\"\"` when the canvas is unavailable. */\n toDataURL: (type?: string, quality?: number) => string;\n /** Export as a `Blob` — what you actually upload. `null` when unavailable. */\n toBlob: (type?: string, quality?: number) => Promise<Blob | null>;\n}\n\nexport interface SignaturePadProps {\n /** Drawing surface width in CSS pixels. Default `400`. */\n width?: number;\n /** Drawing surface height in CSS pixels. Default `160`. */\n height?: number;\n /**\n * Stroke color. Defaults to the canvas' computed `color`, which the\n * stylesheet binds to `--tempest-text` — so the signature follows the theme\n * (including dark mode) instead of being hardcoded black.\n */\n penColor?: string;\n /** Stroke width in CSS pixels. Default `2`. */\n penWidth?: number;\n /** Blocks drawing and dims the surface. */\n disabled?: boolean;\n /** Accessible name of the surface. Default `\"Signature\"`. */\n label?: string;\n /** Called on the first move of each stroke. */\n onBegin?: () => void;\n /** Called when a stroke ends, with the current image as a data URL. */\n onEnd?: (dataUrl: string) => void;\n /** Called whenever the emptiness changes — wire it to a submit button. */\n onEmptyChange?: (isEmpty: boolean) => void;\n /** Renders the Clear/Undo buttons. Default `true`. */\n showActions?: boolean;\n clearLabel?: string;\n undoLabel?: string;\n className?: string;\n}\n\n/**\n * Signature capture on a canvas — the \"sign here\" field of a delivery receipt,\n * a service order, a term of acceptance.\n *\n * Strokes are kept as point lists and the canvas is **redrawn** from them, which\n * is what makes `undo` possible at all: a canvas holds pixels, not history, so\n * removing the last stroke means replaying the rest.\n *\n * The backing store is scaled by `devicePixelRatio`, so the line is crisp on a\n * phone instead of the blurry 1x bitmap a naive canvas produces.\n *\n * @example\n * ```tsx\n * const pad = useRef<SignaturePadHandle>(null);\n * const [empty, setEmpty] = useState(true);\n *\n * async function submit() {\n * const blob = await pad.current?.toBlob(\"image/png\");\n * if (blob) await api.upload(\"/receipts/42/signature\", blob);\n * }\n *\n * <SignaturePad ref={pad} label=\"Assinatura do cliente\" onEmptyChange={setEmpty} />\n * <Button disabled={empty} onClick={submit}>Enviar</Button>\n * ```\n */\nexport const SignaturePad = forwardRef<SignaturePadHandle, SignaturePadProps>(function SignaturePad(\n {\n width = 400,\n height = 160,\n penColor,\n penWidth = 2,\n disabled = false,\n label = \"Signature\",\n onBegin,\n onEnd,\n onEmptyChange,\n showActions = true,\n clearLabel = \"Clear\",\n undoLabel = \"Undo\",\n className,\n },\n ref,\n) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const strokesRef = useRef<Point[][]>([]);\n const drawingRef = useRef(false);\n const [isEmpty, setIsEmpty] = useState(true);\n\n const resolvePenColor = useCallback((): string => {\n if (penColor) return penColor;\n const canvas = canvasRef.current;\n if (!canvas || typeof window === \"undefined\") return \"#101828\";\n return window.getComputedStyle(canvas).color || \"#101828\";\n }, [penColor]);\n\n /**\n * Repaint the whole surface from the stroke list, honouring the pixel ratio.\n *\n * A one-point stroke (a tap) gets a line back to its own origin: `stroke()`\n * over a path with a single point paints nothing, so without it a tap would\n * silently produce no dot while still counting as \"not empty\".\n */\n const redraw = useCallback((): void => {\n const canvas = canvasRef.current;\n const context = canvas?.getContext(\"2d\");\n if (!canvas || !context) return;\n\n const ratio = typeof window === \"undefined\" ? 1 : window.devicePixelRatio || 1;\n canvas.width = width * ratio;\n canvas.height = height * ratio;\n context.setTransform(ratio, 0, 0, ratio, 0, 0);\n context.clearRect(0, 0, width, height);\n\n context.lineWidth = penWidth;\n context.lineCap = \"round\";\n context.lineJoin = \"round\";\n context.strokeStyle = resolvePenColor();\n\n for (const stroke of strokesRef.current) {\n if (stroke.length === 0) continue;\n context.beginPath();\n context.moveTo(stroke[0].x, stroke[0].y);\n for (const point of stroke.slice(1)) {\n context.lineTo(point.x, point.y);\n }\n if (stroke.length === 1) context.lineTo(stroke[0].x, stroke[0].y);\n context.stroke();\n }\n }, [height, penWidth, resolvePenColor, width]);\n\n useEffect(() => {\n redraw();\n }, [redraw]);\n\n const setEmptiness = useCallback(\n (next: boolean): void => {\n setIsEmpty((current) => {\n if (current !== next) onEmptyChange?.(next);\n return next;\n });\n },\n [onEmptyChange],\n );\n\n const pointFrom = useCallback((event: ReactPointerEvent<HTMLCanvasElement>): Point => {\n const rect = canvasRef.current?.getBoundingClientRect();\n return {\n x: event.clientX - (rect?.left ?? 0),\n y: event.clientY - (rect?.top ?? 0),\n };\n }, []);\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (disabled) return;\n drawingRef.current = true;\n strokesRef.current = [...strokesRef.current, [pointFrom(event)]];\n canvasRef.current?.setPointerCapture?.(event.pointerId);\n onBegin?.();\n setEmptiness(false);\n redraw();\n },\n [disabled, onBegin, pointFrom, redraw, setEmptiness],\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (!drawingRef.current || disabled) return;\n const strokes = strokesRef.current;\n strokes[strokes.length - 1].push(pointFrom(event));\n redraw();\n },\n [disabled, pointFrom, redraw],\n );\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (!drawingRef.current) return;\n drawingRef.current = false;\n canvasRef.current?.releasePointerCapture?.(event.pointerId);\n onEnd?.(canvasRef.current?.toDataURL() ?? \"\");\n },\n [onEnd],\n );\n\n const clear = useCallback((): void => {\n strokesRef.current = [];\n setEmptiness(true);\n redraw();\n }, [redraw, setEmptiness]);\n\n const undo = useCallback((): void => {\n strokesRef.current = strokesRef.current.slice(0, -1);\n setEmptiness(strokesRef.current.length === 0);\n redraw();\n }, [redraw, setEmptiness]);\n\n useImperativeHandle(\n ref,\n () => ({\n clear,\n undo,\n isEmpty: () => strokesRef.current.length === 0,\n toDataURL: (type, quality) => canvasRef.current?.toDataURL(type, quality) ?? \"\",\n toBlob: (type, quality) =>\n new Promise((resolve) => {\n const canvas = canvasRef.current;\n if (!canvas?.toBlob) {\n resolve(null);\n return;\n }\n canvas.toBlob((blob) => resolve(blob), type, quality);\n }),\n }),\n [clear, undo],\n );\n\n return (\n <div className={cn(styles.pad, disabled && styles.disabled, className)}>\n <canvas\n ref={canvasRef}\n role=\"img\"\n aria-label={label}\n aria-disabled={disabled || undefined}\n className={styles.canvas}\n style={{ width, height, touchAction: \"none\" }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerLeave={handlePointerUp}\n />\n {showActions ? (\n <div className={styles.actions}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={undo}\n disabled={disabled || isEmpty}\n >\n {undoLabel}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={clear}\n disabled={disabled || isEmpty}\n >\n {clearLabel}\n </Button>\n </div>\n ) : null}\n </div>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"SignaturePad.js","names":[],"sources":["../../../src/components/SignaturePad/SignaturePad.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count, function-lines — the canvas (width,\n * height, penColor, penWidth), the lifecycle an app needs to enable its save button\n * (onBegin, onEnd, onEmptyChange) and the built-in actions with their copy\n * (showActions, clearLabel, undoLabel, label). The body is the stroke buffer plus\n * undo history, which are the same array.\n */\nimport { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport type { PointerEvent as ReactPointerEvent } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { Button } from \"../Button\";\nimport styles from \"./SignaturePad.module.css\";\n\n/** A single sampled point of a stroke, in CSS pixels relative to the canvas. */\ninterface Point {\n x: number;\n y: number;\n}\n\n/** Imperative handle exposed through `ref`. */\nexport interface SignaturePadHandle {\n /** Drop every stroke. */\n clear: () => void;\n /** Drop the last stroke. */\n undo: () => void;\n /** `true` while nothing has been drawn. */\n isEmpty: () => boolean;\n /** Export as a data URL. Returns `\"\"` when the canvas is unavailable. */\n toDataURL: (type?: string, quality?: number) => string;\n /** Export as a `Blob` — what you actually upload. `null` when unavailable. */\n toBlob: (type?: string, quality?: number) => Promise<Blob | null>;\n}\n\nexport interface SignaturePadProps {\n /** Drawing surface width in CSS pixels. Default `400`. */\n width?: number;\n /** Drawing surface height in CSS pixels. Default `160`. */\n height?: number;\n /**\n * Stroke color. Defaults to the canvas' computed `color`, which the\n * stylesheet binds to `--tempest-text` — so the signature follows the theme\n * (including dark mode) instead of being hardcoded black.\n */\n penColor?: string;\n /** Stroke width in CSS pixels. Default `2`. */\n penWidth?: number;\n /** Blocks drawing and dims the surface. */\n disabled?: boolean;\n /** Accessible name of the surface. Default `\"Signature\"`. */\n label?: string;\n /** Called on the first move of each stroke. */\n onBegin?: () => void;\n /** Called when a stroke ends, with the current image as a data URL. */\n onEnd?: (dataUrl: string) => void;\n /** Called whenever the emptiness changes — wire it to a submit button. */\n onEmptyChange?: (isEmpty: boolean) => void;\n /** Renders the Clear/Undo buttons. Default `true`. */\n showActions?: boolean;\n clearLabel?: string;\n undoLabel?: string;\n className?: string;\n}\n\n/**\n * Signature capture on a canvas — the \"sign here\" field of a delivery receipt,\n * a service order, a term of acceptance.\n *\n * Strokes are kept as point lists and the canvas is **redrawn** from them, which\n * is what makes `undo` possible at all: a canvas holds pixels, not history, so\n * removing the last stroke means replaying the rest.\n *\n * The backing store is scaled by `devicePixelRatio`, so the line is crisp on a\n * phone instead of the blurry 1x bitmap a naive canvas produces.\n *\n * @example\n * ```tsx\n * const pad = useRef<SignaturePadHandle>(null);\n * const [empty, setEmpty] = useState(true);\n *\n * async function submit() {\n * const blob = await pad.current?.toBlob(\"image/png\");\n * if (blob) await api.upload(\"/receipts/42/signature\", blob);\n * }\n *\n * <SignaturePad ref={pad} label=\"Assinatura do cliente\" onEmptyChange={setEmpty} />\n * <Button disabled={empty} onClick={submit}>Enviar</Button>\n * ```\n */\nexport const SignaturePad = forwardRef<SignaturePadHandle, SignaturePadProps>(function SignaturePad(\n {\n width = 400,\n height = 160,\n penColor,\n penWidth = 2,\n disabled = false,\n label = \"Signature\",\n onBegin,\n onEnd,\n onEmptyChange,\n showActions = true,\n clearLabel = \"Clear\",\n undoLabel = \"Undo\",\n className,\n },\n ref,\n) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const strokesRef = useRef<Point[][]>([]);\n const drawingRef = useRef(false);\n const [isEmpty, setIsEmpty] = useState(true);\n\n const resolvePenColor = useCallback((): string => {\n if (penColor) return penColor;\n const canvas = canvasRef.current;\n if (!canvas || typeof window === \"undefined\") return \"#101828\";\n return window.getComputedStyle(canvas).color || \"#101828\";\n }, [penColor]);\n\n /**\n * Repaint the whole surface from the stroke list, honouring the pixel ratio.\n *\n * A one-point stroke (a tap) gets a line back to its own origin: `stroke()`\n * over a path with a single point paints nothing, so without it a tap would\n * silently produce no dot while still counting as \"not empty\".\n */\n const redraw = useCallback((): void => {\n const canvas = canvasRef.current;\n const context = canvas?.getContext(\"2d\");\n if (!canvas || !context) return;\n\n const ratio = typeof window === \"undefined\" ? 1 : window.devicePixelRatio || 1;\n canvas.width = width * ratio;\n canvas.height = height * ratio;\n context.setTransform(ratio, 0, 0, ratio, 0, 0);\n context.clearRect(0, 0, width, height);\n\n context.lineWidth = penWidth;\n context.lineCap = \"round\";\n context.lineJoin = \"round\";\n context.strokeStyle = resolvePenColor();\n\n for (const stroke of strokesRef.current) {\n if (stroke.length === 0) continue;\n context.beginPath();\n context.moveTo(stroke[0].x, stroke[0].y);\n for (const point of stroke.slice(1)) {\n context.lineTo(point.x, point.y);\n }\n if (stroke.length === 1) context.lineTo(stroke[0].x, stroke[0].y);\n context.stroke();\n }\n }, [height, penWidth, resolvePenColor, width]);\n\n useEffect(() => {\n redraw();\n }, [redraw]);\n\n const setEmptiness = useCallback(\n (next: boolean): void => {\n setIsEmpty((current) => {\n if (current !== next) onEmptyChange?.(next);\n return next;\n });\n },\n [onEmptyChange],\n );\n\n const pointFrom = useCallback((event: ReactPointerEvent<HTMLCanvasElement>): Point => {\n const rect = canvasRef.current?.getBoundingClientRect();\n return {\n x: event.clientX - (rect?.left ?? 0),\n y: event.clientY - (rect?.top ?? 0),\n };\n }, []);\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (disabled) return;\n drawingRef.current = true;\n strokesRef.current = [...strokesRef.current, [pointFrom(event)]];\n canvasRef.current?.setPointerCapture?.(event.pointerId);\n onBegin?.();\n setEmptiness(false);\n redraw();\n },\n [disabled, onBegin, pointFrom, redraw, setEmptiness],\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (!drawingRef.current || disabled) return;\n const strokes = strokesRef.current;\n strokes[strokes.length - 1].push(pointFrom(event));\n redraw();\n },\n [disabled, pointFrom, redraw],\n );\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): void => {\n if (!drawingRef.current) return;\n drawingRef.current = false;\n canvasRef.current?.releasePointerCapture?.(event.pointerId);\n onEnd?.(canvasRef.current?.toDataURL() ?? \"\");\n },\n [onEnd],\n );\n\n const clear = useCallback((): void => {\n strokesRef.current = [];\n setEmptiness(true);\n redraw();\n }, [redraw, setEmptiness]);\n\n const undo = useCallback((): void => {\n strokesRef.current = strokesRef.current.slice(0, -1);\n setEmptiness(strokesRef.current.length === 0);\n redraw();\n }, [redraw, setEmptiness]);\n\n useImperativeHandle(\n ref,\n () => ({\n clear,\n undo,\n isEmpty: () => strokesRef.current.length === 0,\n toDataURL: (type, quality) => canvasRef.current?.toDataURL(type, quality) ?? \"\",\n toBlob: (type, quality) =>\n new Promise((resolve) => {\n const canvas = canvasRef.current;\n if (!canvas?.toBlob) {\n resolve(null);\n return;\n }\n canvas.toBlob((blob) => resolve(blob), type, quality);\n }),\n }),\n [clear, undo],\n );\n\n return (\n <div className={cn(styles.pad, disabled && styles.disabled, className)}>\n <canvas\n ref={canvasRef}\n role=\"img\"\n aria-label={label}\n aria-disabled={disabled || undefined}\n className={styles.canvas}\n style={{ width, height, touchAction: \"none\" }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerLeave={handlePointerUp}\n />\n {showActions ? (\n <div className={styles.actions}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={undo}\n disabled={disabled || isEmpty}\n >\n {undoLabel}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={clear}\n disabled={disabled || isEmpty}\n >\n {clearLabel}\n </Button>\n </div>\n ) : null}\n </div>\n );\n});\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.cjs","names":[],"sources":["../../../src/components/Slider/Slider.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — min, max, step, value, onChange, formatValue plus\n * the field chrome (label, helperText, disabled, className). Every one is used by\n * the range variant too — the pair is deliberately the same API.\n */\nimport { useCallback, useMemo } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Slider.module.css\";\n\nexport interface SliderProps {\n /** Current value. */\n value: number;\n /** Called with the new value on every change. */\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n helperText?: string;\n disabled?: boolean;\n /** Formatter for the value badge next to the label. Defaults to the raw number. */\n formatValue?: (value: number) => string;\n className?: string;\n}\n\n/**\n * Single-thumb slider built on a native `<input type=\"range\">`, so it stays\n * accessible (keyboard + screen reader) with no positioning libs. The active\n * fill is a percentage-width bar. For a two-thumb range, use `RangeSlider`.\n */\nexport function Slider({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n label,\n helperText,\n disabled = false,\n formatValue,\n className,\n}: SliderProps) {\n const pct = useMemo(() => {\n const range = max - min;\n if (range <= 0) return 0;\n return Math.min(100, Math.max(0, ((value - min) / range) * 100));\n }, [value, min, max]);\n\n const valueText = formatValue?.(value) ?? String(value);\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>): void => {\n onChange(Number(event.target.value));\n },\n [onChange],\n );\n\n return (\n <div className={cn(styles.wrapper, className)}>\n {label && (\n <div className={styles.label}>\n <span>{label}</span>\n <span className={styles.value}>{valueText}</span>\n </div>\n )}\n <div className={styles.field}>\n <div className={styles.track} />\n <div className={styles.fill} style={{ width: `${pct}%` }} />\n <input\n type=\"range\"\n className={styles.input}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={handleChange}\n disabled={disabled}\n aria-label={label ?? \"Slider\"}\n aria-valuetext={valueText}\n />\n </div>\n {helperText && <span className={styles.helper}>{helperText}</span>}\n </div>\n );\n}\n"],"mappings":"6HA8BA,SAAgB,EAAO,CACnB,QACA,WACA,MAAM,EACN,MAAM,IACN,OAAO,EACP,QACA,aACA,WAAW,GACX,cACA,aACY,CACZ,IAAM,GAAA,EAAA,EAAA,QAAA,KAAoB,CACtB,IAAM,EAAQ,EAAM,EAEpB,OADI,GAAS,EAAU,EAChB,KAAK,IAAI,IAAK,KAAK,IAAI,GAAK,EAAQ,GAAO,EAAS,GAAG,CAAC,CACnE,EAAG,CAAC,EAAO,EAAK,CAAG,CAAC,EAEd,EAAY,IAAc,CAAK,GAAK,OAAO,CAAK,EAEhD,GAAA,EAAA,EAAA,YAAA,CACD,GAAqD,CAClD,EAAS,OAAO,EAAM,OAAO,KAAK,CAAC,CACvC,EACA,CAAC,CAAQ,CACb,EAEA,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,WAA5C,CACK,IACG,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,eAAvB,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,CAAY,CAAA,GACnB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,eAAQ,CAAgB,CAAA,CAC/C,KAET,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,eAAvB,EACI,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAQ,CAAA,GAC/B,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAM,MAAO,CAAE,MAAO,GAAG,EAAI,EAAG,CAAI,CAAA,GAC3D,EAAA,EAAA,IAAA,CAAC,QAAD,CACI,KAAK,QACL,UAAW,EAAA,QAAO,MACb,MACA,MACC,OACC,QACP,SAAU,EACA,WACV,aAAY,GAAS,SACrB,iBAAgB,CACnB,CAAA,CACA,IACJ,IAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,gBAAS,CAAiB,CAAA,CAChE,GAEb"}
1
+ {"version":3,"file":"Slider.cjs","names":[],"sources":["../../../src/components/Slider/Slider.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — min, max, step, value, onChange, formatValue plus\n * the field chrome (label, helperText, disabled, className). Every one is used by\n * the range variant too — the pair is deliberately the same API.\n */\nimport { useCallback, useMemo } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Slider.module.css\";\n\nexport interface SliderProps {\n /** Current value. */\n value: number;\n /** Called with the new value on every change. */\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n helperText?: string;\n disabled?: boolean;\n /** Formatter for the value badge next to the label. Defaults to the raw number. */\n formatValue?: (value: number) => string;\n className?: string;\n}\n\n/**\n * Single-thumb slider built on a native `<input type=\"range\">`, so it stays\n * accessible (keyboard + screen reader) with no positioning libs. The active\n * fill is a percentage-width bar. For a two-thumb range, use `RangeSlider`.\n */\nexport function Slider({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n label,\n helperText,\n disabled = false,\n formatValue,\n className,\n}: SliderProps) {\n const pct = useMemo(() => {\n const range = max - min;\n if (range <= 0) return 0;\n return Math.min(100, Math.max(0, ((value - min) / range) * 100));\n }, [value, min, max]);\n\n const valueText = formatValue?.(value) ?? String(value);\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>): void => {\n onChange(Number(event.target.value));\n },\n [onChange],\n );\n\n return (\n <div className={cn(styles.wrapper, className)}>\n {label && (\n <div className={styles.label}>\n <span>{label}</span>\n <span className={styles.value}>{valueText}</span>\n </div>\n )}\n <div className={styles.field}>\n <div className={styles.track} />\n <div className={styles.fill} style={{ width: `${pct}%` }} />\n <input\n type=\"range\"\n className={styles.input}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={handleChange}\n disabled={disabled}\n aria-label={label ?? \"Slider\"}\n aria-valuetext={valueText}\n />\n </div>\n {helperText && <span className={styles.helper}>{helperText}</span>}\n </div>\n );\n}\n"],"mappings":"6HA8BA,SAAgB,EAAO,CACnB,QACA,WACA,MAAM,EACN,MAAM,IACN,OAAO,EACP,QACA,aACA,WAAW,GACX,cACA,aACY,CACZ,IAAM,GAAA,EAAM,EAAA,QAAA,KAAc,CACtB,IAAM,EAAQ,EAAM,EAEpB,OADI,GAAS,EAAU,EAChB,KAAK,IAAI,IAAK,KAAK,IAAI,GAAK,EAAQ,GAAO,EAAS,GAAG,CAAC,CACnE,EAAG,CAAC,EAAO,EAAK,CAAG,CAAC,EAEd,EAAY,IAAc,CAAK,GAAK,OAAO,CAAK,EAEhD,GAAA,EAAe,EAAA,YAAA,CAChB,GAAqD,CAClD,EAAS,OAAO,EAAM,OAAO,KAAK,CAAC,CACvC,EACA,CAAC,CAAQ,CACb,EAEA,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EAA5C,SAAA,CACK,IACG,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,MAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,CAAY,CAAA,GACnB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAgB,CAAA,CAC/C,KAET,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,MAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAQ,CAAA,GAC/B,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAM,MAAO,CAAE,MAAO,GAAG,EAAI,EAAG,CAAI,CAAA,GAC3D,EAAA,EAAA,IAAA,CAAC,QAAD,CACI,KAAK,QACL,UAAW,EAAA,QAAO,MACb,MACA,MACC,OACC,QACP,SAAU,EACA,WACV,aAAY,GAAS,SACrB,iBAAgB,CACnB,CAAA,CACA,IACJ,IAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,OAAS,SAAA,CAAiB,CAAA,CAChE,GAEb"}
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.js","names":[],"sources":["../../../src/components/Slider/Slider.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — min, max, step, value, onChange, formatValue plus\n * the field chrome (label, helperText, disabled, className). Every one is used by\n * the range variant too — the pair is deliberately the same API.\n */\nimport { useCallback, useMemo } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Slider.module.css\";\n\nexport interface SliderProps {\n /** Current value. */\n value: number;\n /** Called with the new value on every change. */\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n helperText?: string;\n disabled?: boolean;\n /** Formatter for the value badge next to the label. Defaults to the raw number. */\n formatValue?: (value: number) => string;\n className?: string;\n}\n\n/**\n * Single-thumb slider built on a native `<input type=\"range\">`, so it stays\n * accessible (keyboard + screen reader) with no positioning libs. The active\n * fill is a percentage-width bar. For a two-thumb range, use `RangeSlider`.\n */\nexport function Slider({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n label,\n helperText,\n disabled = false,\n formatValue,\n className,\n}: SliderProps) {\n const pct = useMemo(() => {\n const range = max - min;\n if (range <= 0) return 0;\n return Math.min(100, Math.max(0, ((value - min) / range) * 100));\n }, [value, min, max]);\n\n const valueText = formatValue?.(value) ?? String(value);\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>): void => {\n onChange(Number(event.target.value));\n },\n [onChange],\n );\n\n return (\n <div className={cn(styles.wrapper, className)}>\n {label && (\n <div className={styles.label}>\n <span>{label}</span>\n <span className={styles.value}>{valueText}</span>\n </div>\n )}\n <div className={styles.field}>\n <div className={styles.track} />\n <div className={styles.fill} style={{ width: `${pct}%` }} />\n <input\n type=\"range\"\n className={styles.input}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={handleChange}\n disabled={disabled}\n aria-label={label ?? \"Slider\"}\n aria-valuetext={valueText}\n />\n </div>\n {helperText && <span className={styles.helper}>{helperText}</span>}\n </div>\n );\n}\n"],"mappings":";;;;;AA8BA,SAAgB,EAAO,EACnB,UACA,aACA,SAAM,GACN,SAAM,KACN,UAAO,GACP,UACA,eACA,cAAW,IACX,gBACA,gBACY;CACZ,IAAM,IAAM,QAAc;EACtB,IAAM,IAAQ,IAAM;EAEpB,OADI,KAAS,IAAU,IAChB,KAAK,IAAI,KAAK,KAAK,IAAI,IAAK,IAAQ,KAAO,IAAS,GAAG,CAAC;CACnE,GAAG;EAAC;EAAO;EAAK;CAAG,CAAC,GAEd,IAAY,IAAc,CAAK,KAAK,OAAO,CAAK,GAEhD,IAAe,GAChB,MAAqD;EAClD,EAAS,OAAO,EAAM,OAAO,KAAK,CAAC;CACvC,GACA,CAAC,CAAQ,CACb;CAEA,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,CAAS;YAA5C;GACK,KACG,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB,CACI,kBAAC,QAAD,EAAA,UAAO,EAAY,CAAA,GACnB,kBAAC,QAAD;KAAM,WAAW,EAAO;eAAQ;IAAgB,CAAA,CAC/C;;GAET,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB;KACI,kBAAC,OAAD,EAAK,WAAW,EAAO,MAAQ,CAAA;KAC/B,kBAAC,OAAD;MAAK,WAAW,EAAO;MAAM,OAAO,EAAE,OAAO,GAAG,EAAI,GAAG;KAAI,CAAA;KAC3D,kBAAC,SAAD;MACI,MAAK;MACL,WAAW,EAAO;MACb;MACA;MACC;MACC;MACP,UAAU;MACA;MACV,cAAY,KAAS;MACrB,kBAAgB;KACnB,CAAA;IACA;;GACJ,KAAc,kBAAC,QAAD;IAAM,WAAW,EAAO;cAAS;GAAiB,CAAA;EAChE;;AAEb"}
1
+ {"version":3,"file":"Slider.js","names":[],"sources":["../../../src/components/Slider/Slider.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — min, max, step, value, onChange, formatValue plus\n * the field chrome (label, helperText, disabled, className). Every one is used by\n * the range variant too — the pair is deliberately the same API.\n */\nimport { useCallback, useMemo } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Slider.module.css\";\n\nexport interface SliderProps {\n /** Current value. */\n value: number;\n /** Called with the new value on every change. */\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n helperText?: string;\n disabled?: boolean;\n /** Formatter for the value badge next to the label. Defaults to the raw number. */\n formatValue?: (value: number) => string;\n className?: string;\n}\n\n/**\n * Single-thumb slider built on a native `<input type=\"range\">`, so it stays\n * accessible (keyboard + screen reader) with no positioning libs. The active\n * fill is a percentage-width bar. For a two-thumb range, use `RangeSlider`.\n */\nexport function Slider({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n label,\n helperText,\n disabled = false,\n formatValue,\n className,\n}: SliderProps) {\n const pct = useMemo(() => {\n const range = max - min;\n if (range <= 0) return 0;\n return Math.min(100, Math.max(0, ((value - min) / range) * 100));\n }, [value, min, max]);\n\n const valueText = formatValue?.(value) ?? String(value);\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>): void => {\n onChange(Number(event.target.value));\n },\n [onChange],\n );\n\n return (\n <div className={cn(styles.wrapper, className)}>\n {label && (\n <div className={styles.label}>\n <span>{label}</span>\n <span className={styles.value}>{valueText}</span>\n </div>\n )}\n <div className={styles.field}>\n <div className={styles.track} />\n <div className={styles.fill} style={{ width: `${pct}%` }} />\n <input\n type=\"range\"\n className={styles.input}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={handleChange}\n disabled={disabled}\n aria-label={label ?? \"Slider\"}\n aria-valuetext={valueText}\n />\n </div>\n {helperText && <span className={styles.helper}>{helperText}</span>}\n </div>\n );\n}\n"],"mappings":";;;;;AA8BA,SAAgB,EAAO,EACnB,UACA,aACA,SAAM,GACN,SAAM,KACN,UAAO,GACP,UACA,eACA,cAAW,IACX,gBACA,gBACY;CACZ,IAAM,IAAM,QAAc;EACtB,IAAM,IAAQ,IAAM;EAEpB,OADI,KAAS,IAAU,IAChB,KAAK,IAAI,KAAK,KAAK,IAAI,IAAK,IAAQ,KAAO,IAAS,GAAG,CAAC;CACnE,GAAG;EAAC;EAAO;EAAK;CAAG,CAAC,GAEd,IAAY,IAAc,CAAK,KAAK,OAAO,CAAK,GAEhD,IAAe,GAChB,MAAqD;EAClD,EAAS,OAAO,EAAM,OAAO,KAAK,CAAC;CACvC,GACA,CAAC,CAAQ,CACb;CAEA,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,CAAS;EAA5C,UAAA;GACK,KACG,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAvB,UAAA,CACI,kBAAC,QAAD,EAAA,UAAO,EAAY,CAAA,GACnB,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAQ,UAAA;IAAgB,CAAA,CAC/C;;GAET,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAvB,UAAA;KACI,kBAAC,OAAD,EAAK,WAAW,EAAO,MAAQ,CAAA;KAC/B,kBAAC,OAAD;MAAK,WAAW,EAAO;MAAM,OAAO,EAAE,OAAO,GAAG,EAAI,GAAG;KAAI,CAAA;KAC3D,kBAAC,SAAD;MACI,MAAK;MACL,WAAW,EAAO;MACb;MACA;MACC;MACC;MACP,UAAU;MACA;MACV,cAAY,KAAS;MACrB,kBAAgB;KACnB,CAAA;IACA;;GACJ,KAAc,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAS,UAAA;GAAiB,CAAA;EAChE;;AAEb"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sparkline.cjs","names":[],"sources":["../../../src/components/Sparkline/Sparkline.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — an inline chart with no chart library: data plus its\n * scale (min, max), its box (width, height), its look (variant, color, showEnd) and\n * its accessibility (valueFormatter, label). The formatter and label matter because\n * a sparkline has no axes to read.\n */\nimport type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { areaPath, barRects, describeSeries, linePath, sparkPoints } from \"./sparkline-geometry\";\nimport styles from \"./Sparkline.module.css\";\n\nexport type SparklineVariant = \"line\" | \"area\" | \"bar\";\n\nexport interface SparklineProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** The series, in order. Non-finite entries are skipped. */\n data: readonly number[];\n /** Drawing width in px. Default `88`. */\n width?: number;\n /** Drawing height in px. Default `24`. */\n height?: number;\n /** Which mark to draw. Default `\"line\"`. */\n variant?: SparklineVariant;\n /** Any CSS colour. Defaults to the first chart series token. */\n color?: string;\n /** Draw a dot on the last point. Default `true` for line and area. */\n showEnd?: boolean;\n /** Force the low end of the value axis — use it to compare several sparklines. */\n min?: number;\n /** Force the high end. */\n max?: number;\n /** Render a value; used in the accessible description. */\n valueFormatter?: (value: number) => string;\n /**\n * Accessible name. Defaults to a sentence describing the series.\n *\n * Pass one when the surrounding text already says what is plotted — the default\n * still appends the shape, so a caller never ends up with an unlabelled image.\n */\n label?: string;\n}\n\n/**\n * A tiny inline chart: shape only, no axes, no legend.\n *\n * Sized to sit in a table cell or beside a number, which is why it is plain SVG on\n * the root entry rather than a recharts wrapper — a sparkline in a data table should\n * not oblige an app to install a charting library.\n *\n * It carries `role=\"img\"` and a spoken description of the series (direction, ends,\n * extremes). Without that it is an unlabelled image: a sparkline has no axis or\n * legend to fall back on, so a screen reader would reach it and read nothing. Pair it\n * with the number it annotates — the shape is context, never the only way to read the\n * value.\n *\n * @example\n * <Sparkline data={last30Days} />\n * <Sparkline data={revenue} variant=\"area\" width={120} height={32} />\n *\n * // Same axis across a column, so the rows are comparable\n * <Sparkline data={row.series} min={0} max={columnMax} />\n */\nexport function Sparkline({\n data,\n width = 88,\n height = 24,\n variant = \"line\",\n color = \"var(--tempest-chart-1)\",\n showEnd,\n min,\n max,\n valueFormatter,\n label,\n className,\n ...rest\n}: SparklineProps) {\n const points = sparkPoints({ values: data, width, height, min, max });\n const description = label ?? describeSeries(data, valueFormatter);\n const withEnd = showEnd ?? variant !== \"bar\";\n const last = points[points.length - 1];\n\n /*\n * Bars grow from the bottom of the box; line and area close against it. Both use\n * the same edge so a sparkline swapped between variants keeps its footprint.\n */\n const baselineY = height - 2;\n\n return (\n <span className={cn(styles.wrapper, className)} {...rest}>\n <svg\n className={styles.svg}\n width={width}\n height={height}\n viewBox={`0 0 ${width} ${height}`}\n role=\"img\"\n aria-label={description}\n >\n {points.length > 0 && variant === \"area\" && (\n <path d={areaPath(points, baselineY)} fill={color} className={styles.area} />\n )}\n\n {points.length > 0 && variant !== \"bar\" && (\n <path\n d={linePath(points)}\n fill=\"none\"\n stroke={color}\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n )}\n\n {variant === \"bar\" &&\n barRects(points, { width, baselineY }).map((rect) => (\n <rect\n key={rect.point.index}\n x={rect.x}\n y={rect.y}\n width={rect.width}\n height={rect.height}\n rx={1}\n fill={color}\n />\n ))}\n\n {withEnd && last && (\n /*\n * The ring is drawn in the surface colour rather than as a stroke on\n * the dot: it keeps the marker legible where it sits on top of the\n * line without adding ink that is not data.\n */\n <circle\n cx={last.x}\n cy={last.y}\n r={3}\n fill={color}\n stroke=\"var(--tempest-bg)\"\n strokeWidth={2}\n />\n )}\n </svg>\n </span>\n );\n}\n"],"mappings":"mJA+DA,SAAgB,EAAU,CACtB,OACA,QAAQ,GACR,SAAS,GACT,UAAU,OACV,QAAQ,yBACR,UACA,MACA,MACA,iBACA,QACA,YACA,GAAG,GACY,CACf,IAAM,EAAS,EAAA,YAAY,CAAE,OAAQ,EAAM,QAAO,SAAQ,MAAK,KAAI,CAAC,EAC9D,EAAc,GAAS,EAAA,eAAe,EAAM,CAAc,EAC1D,EAAU,GAAW,IAAY,MACjC,EAAO,EAAO,EAAO,OAAS,GAM9B,EAAY,EAAS,EAE3B,OACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EAAG,GAAI,YAChD,EAAA,EAAA,KAAA,CAAC,MAAD,CACI,UAAW,EAAA,QAAO,IACX,QACC,SACR,QAAS,OAAO,EAAM,GAAG,IACzB,KAAK,MACL,aAAY,WANhB,CAQK,EAAO,OAAS,GAAK,IAAY,SAC9B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAG,EAAA,SAAS,EAAQ,CAAS,EAAG,KAAM,EAAO,UAAW,EAAA,QAAO,IAAO,CAAA,EAG/E,EAAO,OAAS,GAAK,IAAY,QAC9B,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,EAAG,EAAA,SAAS,CAAM,EAClB,KAAK,OACL,OAAQ,EACR,YAAa,EACb,cAAc,QACd,eAAe,OAClB,CAAA,EAGJ,IAAY,OACT,EAAA,SAAS,EAAQ,CAAE,QAAO,WAAU,CAAC,CAAC,CAAC,IAAK,IACxC,EAAA,EAAA,IAAA,CAAC,OAAD,CAEI,EAAG,EAAK,EACR,EAAG,EAAK,EACR,MAAO,EAAK,MACZ,OAAQ,EAAK,OACb,GAAI,EACJ,KAAM,CACT,EAPQ,EAAK,MAAM,KAOnB,CACJ,EAEJ,GAAW,IAMR,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,GAAI,EAAK,EACT,GAAI,EAAK,EACT,EAAG,EACH,KAAM,EACN,OAAO,oBACP,YAAa,CAChB,CAAA,CAEJ,GACH,CAAA,CAEd"}
1
+ {"version":3,"file":"Sparkline.cjs","names":[],"sources":["../../../src/components/Sparkline/Sparkline.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — an inline chart with no chart library: data plus its\n * scale (min, max), its box (width, height), its look (variant, color, showEnd) and\n * its accessibility (valueFormatter, label). The formatter and label matter because\n * a sparkline has no axes to read.\n */\nimport type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { areaPath, barRects, describeSeries, linePath, sparkPoints } from \"./sparkline-geometry\";\nimport styles from \"./Sparkline.module.css\";\n\nexport type SparklineVariant = \"line\" | \"area\" | \"bar\";\n\nexport interface SparklineProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** The series, in order. Non-finite entries are skipped. */\n data: readonly number[];\n /** Drawing width in px. Default `88`. */\n width?: number;\n /** Drawing height in px. Default `24`. */\n height?: number;\n /** Which mark to draw. Default `\"line\"`. */\n variant?: SparklineVariant;\n /** Any CSS colour. Defaults to the first chart series token. */\n color?: string;\n /** Draw a dot on the last point. Default `true` for line and area. */\n showEnd?: boolean;\n /** Force the low end of the value axis — use it to compare several sparklines. */\n min?: number;\n /** Force the high end. */\n max?: number;\n /** Render a value; used in the accessible description. */\n valueFormatter?: (value: number) => string;\n /**\n * Accessible name. Defaults to a sentence describing the series.\n *\n * Pass one when the surrounding text already says what is plotted — the default\n * still appends the shape, so a caller never ends up with an unlabelled image.\n */\n label?: string;\n}\n\n/**\n * A tiny inline chart: shape only, no axes, no legend.\n *\n * Sized to sit in a table cell or beside a number, which is why it is plain SVG on\n * the root entry rather than a recharts wrapper — a sparkline in a data table should\n * not oblige an app to install a charting library.\n *\n * It carries `role=\"img\"` and a spoken description of the series (direction, ends,\n * extremes). Without that it is an unlabelled image: a sparkline has no axis or\n * legend to fall back on, so a screen reader would reach it and read nothing. Pair it\n * with the number it annotates — the shape is context, never the only way to read the\n * value.\n *\n * @example\n * <Sparkline data={last30Days} />\n * <Sparkline data={revenue} variant=\"area\" width={120} height={32} />\n *\n * // Same axis across a column, so the rows are comparable\n * <Sparkline data={row.series} min={0} max={columnMax} />\n */\nexport function Sparkline({\n data,\n width = 88,\n height = 24,\n variant = \"line\",\n color = \"var(--tempest-chart-1)\",\n showEnd,\n min,\n max,\n valueFormatter,\n label,\n className,\n ...rest\n}: SparklineProps) {\n const points = sparkPoints({ values: data, width, height, min, max });\n const description = label ?? describeSeries(data, valueFormatter);\n const withEnd = showEnd ?? variant !== \"bar\";\n const last = points[points.length - 1];\n\n /*\n * Bars grow from the bottom of the box; line and area close against it. Both use\n * the same edge so a sparkline swapped between variants keeps its footprint.\n */\n const baselineY = height - 2;\n\n return (\n <span className={cn(styles.wrapper, className)} {...rest}>\n <svg\n className={styles.svg}\n width={width}\n height={height}\n viewBox={`0 0 ${width} ${height}`}\n role=\"img\"\n aria-label={description}\n >\n {points.length > 0 && variant === \"area\" && (\n <path d={areaPath(points, baselineY)} fill={color} className={styles.area} />\n )}\n\n {points.length > 0 && variant !== \"bar\" && (\n <path\n d={linePath(points)}\n fill=\"none\"\n stroke={color}\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n )}\n\n {variant === \"bar\" &&\n barRects(points, { width, baselineY }).map((rect) => (\n <rect\n key={rect.point.index}\n x={rect.x}\n y={rect.y}\n width={rect.width}\n height={rect.height}\n rx={1}\n fill={color}\n />\n ))}\n\n {withEnd && last && (\n /*\n * The ring is drawn in the surface colour rather than as a stroke on\n * the dot: it keeps the marker legible where it sits on top of the\n * line without adding ink that is not data.\n */\n <circle\n cx={last.x}\n cy={last.y}\n r={3}\n fill={color}\n stroke=\"var(--tempest-bg)\"\n strokeWidth={2}\n />\n )}\n </svg>\n </span>\n );\n}\n"],"mappings":"mJA+DA,SAAgB,EAAU,CACtB,OACA,QAAQ,GACR,SAAS,GACT,UAAU,OACV,QAAQ,yBACR,UACA,MACA,MACA,iBACA,QACA,YACA,GAAG,GACY,CACf,IAAM,EAAS,EAAA,YAAY,CAAE,OAAQ,EAAM,QAAO,SAAQ,MAAK,KAAI,CAAC,EAC9D,EAAc,GAAS,EAAA,eAAe,EAAM,CAAc,EAC1D,EAAU,GAAW,IAAY,MACjC,EAAO,EAAO,EAAO,OAAS,GAM9B,EAAY,EAAS,EAE3B,OACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EAAG,GAAI,EAChD,UAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CACI,UAAW,EAAA,QAAO,IACX,QACC,SACR,QAAS,OAAO,EAAM,GAAG,IACzB,KAAK,MACL,aAAY,EANhB,SAAA,CAQK,EAAO,OAAS,GAAK,IAAY,SAC9B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAG,EAAA,SAAS,EAAQ,CAAS,EAAG,KAAM,EAAO,UAAW,EAAA,QAAO,IAAO,CAAA,EAG/E,EAAO,OAAS,GAAK,IAAY,QAC9B,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,EAAG,EAAA,SAAS,CAAM,EAClB,KAAK,OACL,OAAQ,EACR,YAAa,EACb,cAAc,QACd,eAAe,OAClB,CAAA,EAGJ,IAAY,OACT,EAAA,SAAS,EAAQ,CAAE,QAAO,WAAU,CAAC,CAAC,CAAC,IAAK,IACxC,EAAA,EAAA,IAAA,CAAC,OAAD,CAEI,EAAG,EAAK,EACR,EAAG,EAAK,EACR,MAAO,EAAK,MACZ,OAAQ,EAAK,OACb,GAAI,EACJ,KAAM,CACT,EAPQ,EAAK,MAAM,KAOnB,CACJ,EAEJ,GAAW,IAMR,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,GAAI,EAAK,EACT,GAAI,EAAK,EACT,EAAG,EACH,KAAM,EACN,OAAO,oBACP,YAAa,CAChB,CAAA,CAEJ,GACH,CAAA,CAEd"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sparkline.js","names":[],"sources":["../../../src/components/Sparkline/Sparkline.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — an inline chart with no chart library: data plus its\n * scale (min, max), its box (width, height), its look (variant, color, showEnd) and\n * its accessibility (valueFormatter, label). The formatter and label matter because\n * a sparkline has no axes to read.\n */\nimport type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { areaPath, barRects, describeSeries, linePath, sparkPoints } from \"./sparkline-geometry\";\nimport styles from \"./Sparkline.module.css\";\n\nexport type SparklineVariant = \"line\" | \"area\" | \"bar\";\n\nexport interface SparklineProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** The series, in order. Non-finite entries are skipped. */\n data: readonly number[];\n /** Drawing width in px. Default `88`. */\n width?: number;\n /** Drawing height in px. Default `24`. */\n height?: number;\n /** Which mark to draw. Default `\"line\"`. */\n variant?: SparklineVariant;\n /** Any CSS colour. Defaults to the first chart series token. */\n color?: string;\n /** Draw a dot on the last point. Default `true` for line and area. */\n showEnd?: boolean;\n /** Force the low end of the value axis — use it to compare several sparklines. */\n min?: number;\n /** Force the high end. */\n max?: number;\n /** Render a value; used in the accessible description. */\n valueFormatter?: (value: number) => string;\n /**\n * Accessible name. Defaults to a sentence describing the series.\n *\n * Pass one when the surrounding text already says what is plotted — the default\n * still appends the shape, so a caller never ends up with an unlabelled image.\n */\n label?: string;\n}\n\n/**\n * A tiny inline chart: shape only, no axes, no legend.\n *\n * Sized to sit in a table cell or beside a number, which is why it is plain SVG on\n * the root entry rather than a recharts wrapper — a sparkline in a data table should\n * not oblige an app to install a charting library.\n *\n * It carries `role=\"img\"` and a spoken description of the series (direction, ends,\n * extremes). Without that it is an unlabelled image: a sparkline has no axis or\n * legend to fall back on, so a screen reader would reach it and read nothing. Pair it\n * with the number it annotates — the shape is context, never the only way to read the\n * value.\n *\n * @example\n * <Sparkline data={last30Days} />\n * <Sparkline data={revenue} variant=\"area\" width={120} height={32} />\n *\n * // Same axis across a column, so the rows are comparable\n * <Sparkline data={row.series} min={0} max={columnMax} />\n */\nexport function Sparkline({\n data,\n width = 88,\n height = 24,\n variant = \"line\",\n color = \"var(--tempest-chart-1)\",\n showEnd,\n min,\n max,\n valueFormatter,\n label,\n className,\n ...rest\n}: SparklineProps) {\n const points = sparkPoints({ values: data, width, height, min, max });\n const description = label ?? describeSeries(data, valueFormatter);\n const withEnd = showEnd ?? variant !== \"bar\";\n const last = points[points.length - 1];\n\n /*\n * Bars grow from the bottom of the box; line and area close against it. Both use\n * the same edge so a sparkline swapped between variants keeps its footprint.\n */\n const baselineY = height - 2;\n\n return (\n <span className={cn(styles.wrapper, className)} {...rest}>\n <svg\n className={styles.svg}\n width={width}\n height={height}\n viewBox={`0 0 ${width} ${height}`}\n role=\"img\"\n aria-label={description}\n >\n {points.length > 0 && variant === \"area\" && (\n <path d={areaPath(points, baselineY)} fill={color} className={styles.area} />\n )}\n\n {points.length > 0 && variant !== \"bar\" && (\n <path\n d={linePath(points)}\n fill=\"none\"\n stroke={color}\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n )}\n\n {variant === \"bar\" &&\n barRects(points, { width, baselineY }).map((rect) => (\n <rect\n key={rect.point.index}\n x={rect.x}\n y={rect.y}\n width={rect.width}\n height={rect.height}\n rx={1}\n fill={color}\n />\n ))}\n\n {withEnd && last && (\n /*\n * The ring is drawn in the surface colour rather than as a stroke on\n * the dot: it keeps the marker legible where it sits on top of the\n * line without adding ink that is not data.\n */\n <circle\n cx={last.x}\n cy={last.y}\n r={3}\n fill={color}\n stroke=\"var(--tempest-bg)\"\n strokeWidth={2}\n />\n )}\n </svg>\n </span>\n );\n}\n"],"mappings":";;;;;AA+DA,SAAgB,EAAU,EACtB,SACA,WAAQ,IACR,YAAS,IACT,aAAU,QACV,WAAQ,0BACR,YACA,QACA,QACA,mBACA,UACA,cACA,GAAG,KACY;CACf,IAAM,IAAS,EAAY;EAAE,QAAQ;EAAM;EAAO;EAAQ;EAAK;CAAI,CAAC,GAC9D,IAAc,KAAS,EAAe,GAAM,CAAc,GAC1D,IAAU,KAAW,MAAY,OACjC,IAAO,EAAO,EAAO,SAAS,IAM9B,IAAY,IAAS;CAE3B,OACI,kBAAC,QAAD;EAAM,WAAW,EAAG,EAAO,SAAS,CAAS;EAAG,GAAI;YAChD,kBAAC,OAAD;GACI,WAAW,EAAO;GACX;GACC;GACR,SAAS,OAAO,EAAM,GAAG;GACzB,MAAK;GACL,cAAY;aANhB;IAQK,EAAO,SAAS,KAAK,MAAY,UAC9B,kBAAC,QAAD;KAAM,GAAG,EAAS,GAAQ,CAAS;KAAG,MAAM;KAAO,WAAW,EAAO;IAAO,CAAA;IAG/E,EAAO,SAAS,KAAK,MAAY,SAC9B,kBAAC,QAAD;KACI,GAAG,EAAS,CAAM;KAClB,MAAK;KACL,QAAQ;KACR,aAAa;KACb,eAAc;KACd,gBAAe;IAClB,CAAA;IAGJ,MAAY,SACT,EAAS,GAAQ;KAAE;KAAO;IAAU,CAAC,CAAC,CAAC,KAAK,MACxC,kBAAC,QAAD;KAEI,GAAG,EAAK;KACR,GAAG,EAAK;KACR,OAAO,EAAK;KACZ,QAAQ,EAAK;KACb,IAAI;KACJ,MAAM;IACT,GAPQ,EAAK,MAAM,KAOnB,CACJ;IAEJ,KAAW,KAMR,kBAAC,UAAD;KACI,IAAI,EAAK;KACT,IAAI,EAAK;KACT,GAAG;KACH,MAAM;KACN,QAAO;KACP,aAAa;IAChB,CAAA;GAEJ;;CACH,CAAA;AAEd"}
1
+ {"version":3,"file":"Sparkline.js","names":[],"sources":["../../../src/components/Sparkline/Sparkline.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — an inline chart with no chart library: data plus its\n * scale (min, max), its box (width, height), its look (variant, color, showEnd) and\n * its accessibility (valueFormatter, label). The formatter and label matter because\n * a sparkline has no axes to read.\n */\nimport type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { areaPath, barRects, describeSeries, linePath, sparkPoints } from \"./sparkline-geometry\";\nimport styles from \"./Sparkline.module.css\";\n\nexport type SparklineVariant = \"line\" | \"area\" | \"bar\";\n\nexport interface SparklineProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** The series, in order. Non-finite entries are skipped. */\n data: readonly number[];\n /** Drawing width in px. Default `88`. */\n width?: number;\n /** Drawing height in px. Default `24`. */\n height?: number;\n /** Which mark to draw. Default `\"line\"`. */\n variant?: SparklineVariant;\n /** Any CSS colour. Defaults to the first chart series token. */\n color?: string;\n /** Draw a dot on the last point. Default `true` for line and area. */\n showEnd?: boolean;\n /** Force the low end of the value axis — use it to compare several sparklines. */\n min?: number;\n /** Force the high end. */\n max?: number;\n /** Render a value; used in the accessible description. */\n valueFormatter?: (value: number) => string;\n /**\n * Accessible name. Defaults to a sentence describing the series.\n *\n * Pass one when the surrounding text already says what is plotted — the default\n * still appends the shape, so a caller never ends up with an unlabelled image.\n */\n label?: string;\n}\n\n/**\n * A tiny inline chart: shape only, no axes, no legend.\n *\n * Sized to sit in a table cell or beside a number, which is why it is plain SVG on\n * the root entry rather than a recharts wrapper — a sparkline in a data table should\n * not oblige an app to install a charting library.\n *\n * It carries `role=\"img\"` and a spoken description of the series (direction, ends,\n * extremes). Without that it is an unlabelled image: a sparkline has no axis or\n * legend to fall back on, so a screen reader would reach it and read nothing. Pair it\n * with the number it annotates — the shape is context, never the only way to read the\n * value.\n *\n * @example\n * <Sparkline data={last30Days} />\n * <Sparkline data={revenue} variant=\"area\" width={120} height={32} />\n *\n * // Same axis across a column, so the rows are comparable\n * <Sparkline data={row.series} min={0} max={columnMax} />\n */\nexport function Sparkline({\n data,\n width = 88,\n height = 24,\n variant = \"line\",\n color = \"var(--tempest-chart-1)\",\n showEnd,\n min,\n max,\n valueFormatter,\n label,\n className,\n ...rest\n}: SparklineProps) {\n const points = sparkPoints({ values: data, width, height, min, max });\n const description = label ?? describeSeries(data, valueFormatter);\n const withEnd = showEnd ?? variant !== \"bar\";\n const last = points[points.length - 1];\n\n /*\n * Bars grow from the bottom of the box; line and area close against it. Both use\n * the same edge so a sparkline swapped between variants keeps its footprint.\n */\n const baselineY = height - 2;\n\n return (\n <span className={cn(styles.wrapper, className)} {...rest}>\n <svg\n className={styles.svg}\n width={width}\n height={height}\n viewBox={`0 0 ${width} ${height}`}\n role=\"img\"\n aria-label={description}\n >\n {points.length > 0 && variant === \"area\" && (\n <path d={areaPath(points, baselineY)} fill={color} className={styles.area} />\n )}\n\n {points.length > 0 && variant !== \"bar\" && (\n <path\n d={linePath(points)}\n fill=\"none\"\n stroke={color}\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n )}\n\n {variant === \"bar\" &&\n barRects(points, { width, baselineY }).map((rect) => (\n <rect\n key={rect.point.index}\n x={rect.x}\n y={rect.y}\n width={rect.width}\n height={rect.height}\n rx={1}\n fill={color}\n />\n ))}\n\n {withEnd && last && (\n /*\n * The ring is drawn in the surface colour rather than as a stroke on\n * the dot: it keeps the marker legible where it sits on top of the\n * line without adding ink that is not data.\n */\n <circle\n cx={last.x}\n cy={last.y}\n r={3}\n fill={color}\n stroke=\"var(--tempest-bg)\"\n strokeWidth={2}\n />\n )}\n </svg>\n </span>\n );\n}\n"],"mappings":";;;;;AA+DA,SAAgB,EAAU,EACtB,SACA,WAAQ,IACR,YAAS,IACT,aAAU,QACV,WAAQ,0BACR,YACA,QACA,QACA,mBACA,UACA,cACA,GAAG,KACY;CACf,IAAM,IAAS,EAAY;EAAE,QAAQ;EAAM;EAAO;EAAQ;EAAK;CAAI,CAAC,GAC9D,IAAc,KAAS,EAAe,GAAM,CAAc,GAC1D,IAAU,KAAW,MAAY,OACjC,IAAO,EAAO,EAAO,SAAS,IAM9B,IAAY,IAAS;CAE3B,OACI,kBAAC,QAAD;EAAM,WAAW,EAAG,EAAO,SAAS,CAAS;EAAG,GAAI;EAChD,UAAA,kBAAC,OAAD;GACI,WAAW,EAAO;GACX;GACC;GACR,SAAS,OAAO,EAAM,GAAG;GACzB,MAAK;GACL,cAAY;GANhB,UAAA;IAQK,EAAO,SAAS,KAAK,MAAY,UAC9B,kBAAC,QAAD;KAAM,GAAG,EAAS,GAAQ,CAAS;KAAG,MAAM;KAAO,WAAW,EAAO;IAAO,CAAA;IAG/E,EAAO,SAAS,KAAK,MAAY,SAC9B,kBAAC,QAAD;KACI,GAAG,EAAS,CAAM;KAClB,MAAK;KACL,QAAQ;KACR,aAAa;KACb,eAAc;KACd,gBAAe;IAClB,CAAA;IAGJ,MAAY,SACT,EAAS,GAAQ;KAAE;KAAO;IAAU,CAAC,CAAC,CAAC,KAAK,MACxC,kBAAC,QAAD;KAEI,GAAG,EAAK;KACR,GAAG,EAAK;KACR,OAAO,EAAK;KACZ,QAAQ,EAAK;KACb,IAAI;KACJ,MAAM;IACT,GAPQ,EAAK,MAAM,KAOnB,CACJ;IAEJ,KAAW,KAMR,kBAAC,UAAD;KACI,IAAI,EAAK;KACT,IAAI,EAAK;KACT,GAAG;KACH,MAAM;KACN,QAAO;KACP,aAAa;IAChB,CAAA;GAEJ;;CACH,CAAA;AAEd"}
@@ -1 +1 @@
1
- {"version":3,"file":"Spinner.cjs","names":[],"sources":["../../../src/components/Spinner/Spinner.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Spinner.module.css\";\n\nexport type SpinnerSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport interface SpinnerProps {\n size?: SpinnerSize;\n className?: string;\n /** Accessible label announced by screen readers. */\n label?: string;\n /**\n * Visible caption rendered under the spinner. When set, the spinner and\n * caption are wrapped in a centered column.\n */\n caption?: ReactNode;\n /**\n * Center the spinner inside a full-area overlay (fills the nearest\n * positioned ancestor; pair with a relative container or a route fallback).\n * Implies the wrapped layout.\n */\n overlay?: boolean;\n}\n\n/**\n * Loading spinner with preset sizes (xs..xl). Provide `label` for screen\n * readers, `caption` for a visible message, and `overlay` to center it inside a\n * full-area container (e.g. a Suspense / route fallback).\n *\n * @example\n * <Spinner />\n * <Spinner size=\"lg\" caption=\"Carregando…\" overlay />\n */\nexport function Spinner({\n size = \"md\",\n className,\n label = \"Carregando\",\n caption,\n overlay = false,\n}: SpinnerProps) {\n const dot = <span aria-hidden className={cn(styles.spinner, styles[size])} />;\n\n if (!overlay && caption === undefined) {\n return (\n <span\n role=\"status\"\n aria-label={label}\n className={cn(styles.spinner, styles[size], className)}\n />\n );\n }\n\n return (\n <div\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n className={cn(styles.wrap, overlay && styles.overlay, className)}\n >\n {dot}\n {caption !== undefined && <span className={styles.caption}>{caption}</span>}\n </div>\n );\n}\n"],"mappings":"2GAiCA,SAAgB,EAAQ,CACpB,OAAO,KACP,YACA,QAAQ,aACR,UACA,UAAU,IACG,CACb,IAAM,GAAM,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,cAAA,GAAY,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,EAAA,QAAO,EAAK,CAAI,CAAA,EAY5E,MAVI,CAAC,GAAW,IAAY,IAAA,IAEpB,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,KAAK,SACL,aAAY,EACZ,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,EAAA,QAAO,GAAO,CAAS,CACxD,CAAA,GAKL,EAAA,EAAA,KAAA,CAAC,MAAD,CACI,KAAK,SACL,aAAY,EACZ,YAAU,SACV,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,GAAW,EAAA,QAAO,QAAS,CAAS,WAJnE,CAMK,EACA,IAAY,IAAA,KAAa,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,iBAAU,CAAc,CAAA,CACzE,GAEb"}
1
+ {"version":3,"file":"Spinner.cjs","names":[],"sources":["../../../src/components/Spinner/Spinner.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Spinner.module.css\";\n\nexport type SpinnerSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport interface SpinnerProps {\n size?: SpinnerSize;\n className?: string;\n /** Accessible label announced by screen readers. */\n label?: string;\n /**\n * Visible caption rendered under the spinner. When set, the spinner and\n * caption are wrapped in a centered column.\n */\n caption?: ReactNode;\n /**\n * Center the spinner inside a full-area overlay (fills the nearest\n * positioned ancestor; pair with a relative container or a route fallback).\n * Implies the wrapped layout.\n */\n overlay?: boolean;\n}\n\n/**\n * Loading spinner with preset sizes (xs..xl). Provide `label` for screen\n * readers, `caption` for a visible message, and `overlay` to center it inside a\n * full-area container (e.g. a Suspense / route fallback).\n *\n * @example\n * <Spinner />\n * <Spinner size=\"lg\" caption=\"Carregando…\" overlay />\n */\nexport function Spinner({\n size = \"md\",\n className,\n label = \"Carregando\",\n caption,\n overlay = false,\n}: SpinnerProps) {\n const dot = <span aria-hidden className={cn(styles.spinner, styles[size])} />;\n\n if (!overlay && caption === undefined) {\n return (\n <span\n role=\"status\"\n aria-label={label}\n className={cn(styles.spinner, styles[size], className)}\n />\n );\n }\n\n return (\n <div\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n className={cn(styles.wrap, overlay && styles.overlay, className)}\n >\n {dot}\n {caption !== undefined && <span className={styles.caption}>{caption}</span>}\n </div>\n );\n}\n"],"mappings":"2GAiCA,SAAgB,EAAQ,CACpB,OAAO,KACP,YACA,QAAQ,aACR,UACA,UAAU,IACG,CACb,IAAM,GAAM,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,cAAA,GAAY,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,EAAA,QAAO,EAAK,CAAI,CAAA,EAY5E,MAVI,CAAC,GAAW,IAAY,IAAA,IAEpB,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,KAAK,SACL,aAAY,EACZ,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,EAAA,QAAO,GAAO,CAAS,CACxD,CAAA,GAKL,EAAA,EAAA,KAAA,CAAC,MAAD,CACI,KAAK,SACL,aAAY,EACZ,YAAU,SACV,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,GAAW,EAAA,QAAO,QAAS,CAAS,EAJnE,SAAA,CAMK,EACA,IAAY,IAAA,KAAa,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,QAAU,SAAA,CAAc,CAAA,CACzE,GAEb"}
@@ -1 +1 @@
1
- {"version":3,"file":"Spinner.js","names":[],"sources":["../../../src/components/Spinner/Spinner.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Spinner.module.css\";\n\nexport type SpinnerSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport interface SpinnerProps {\n size?: SpinnerSize;\n className?: string;\n /** Accessible label announced by screen readers. */\n label?: string;\n /**\n * Visible caption rendered under the spinner. When set, the spinner and\n * caption are wrapped in a centered column.\n */\n caption?: ReactNode;\n /**\n * Center the spinner inside a full-area overlay (fills the nearest\n * positioned ancestor; pair with a relative container or a route fallback).\n * Implies the wrapped layout.\n */\n overlay?: boolean;\n}\n\n/**\n * Loading spinner with preset sizes (xs..xl). Provide `label` for screen\n * readers, `caption` for a visible message, and `overlay` to center it inside a\n * full-area container (e.g. a Suspense / route fallback).\n *\n * @example\n * <Spinner />\n * <Spinner size=\"lg\" caption=\"Carregando…\" overlay />\n */\nexport function Spinner({\n size = \"md\",\n className,\n label = \"Carregando\",\n caption,\n overlay = false,\n}: SpinnerProps) {\n const dot = <span aria-hidden className={cn(styles.spinner, styles[size])} />;\n\n if (!overlay && caption === undefined) {\n return (\n <span\n role=\"status\"\n aria-label={label}\n className={cn(styles.spinner, styles[size], className)}\n />\n );\n }\n\n return (\n <div\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n className={cn(styles.wrap, overlay && styles.overlay, className)}\n >\n {dot}\n {caption !== undefined && <span className={styles.caption}>{caption}</span>}\n </div>\n );\n}\n"],"mappings":";;;;AAiCA,SAAgB,EAAQ,EACpB,UAAO,MACP,cACA,WAAQ,cACR,YACA,aAAU,MACG;CACb,IAAM,IAAM,kBAAC,QAAD;EAAM,eAAA;EAAY,WAAW,EAAG,EAAO,SAAS,EAAO,EAAK;CAAI,CAAA;CAY5E,OAVI,CAAC,KAAW,MAAY,KAAA,IAEpB,kBAAC,QAAD;EACI,MAAK;EACL,cAAY;EACZ,WAAW,EAAG,EAAO,SAAS,EAAO,IAAO,CAAS;CACxD,CAAA,IAKL,kBAAC,OAAD;EACI,MAAK;EACL,cAAY;EACZ,aAAU;EACV,WAAW,EAAG,EAAO,MAAM,KAAW,EAAO,SAAS,CAAS;YAJnE,CAMK,GACA,MAAY,KAAA,KAAa,kBAAC,QAAD;GAAM,WAAW,EAAO;aAAU;EAAc,CAAA,CACzE;;AAEb"}
1
+ {"version":3,"file":"Spinner.js","names":[],"sources":["../../../src/components/Spinner/Spinner.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Spinner.module.css\";\n\nexport type SpinnerSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport interface SpinnerProps {\n size?: SpinnerSize;\n className?: string;\n /** Accessible label announced by screen readers. */\n label?: string;\n /**\n * Visible caption rendered under the spinner. When set, the spinner and\n * caption are wrapped in a centered column.\n */\n caption?: ReactNode;\n /**\n * Center the spinner inside a full-area overlay (fills the nearest\n * positioned ancestor; pair with a relative container or a route fallback).\n * Implies the wrapped layout.\n */\n overlay?: boolean;\n}\n\n/**\n * Loading spinner with preset sizes (xs..xl). Provide `label` for screen\n * readers, `caption` for a visible message, and `overlay` to center it inside a\n * full-area container (e.g. a Suspense / route fallback).\n *\n * @example\n * <Spinner />\n * <Spinner size=\"lg\" caption=\"Carregando…\" overlay />\n */\nexport function Spinner({\n size = \"md\",\n className,\n label = \"Carregando\",\n caption,\n overlay = false,\n}: SpinnerProps) {\n const dot = <span aria-hidden className={cn(styles.spinner, styles[size])} />;\n\n if (!overlay && caption === undefined) {\n return (\n <span\n role=\"status\"\n aria-label={label}\n className={cn(styles.spinner, styles[size], className)}\n />\n );\n }\n\n return (\n <div\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n className={cn(styles.wrap, overlay && styles.overlay, className)}\n >\n {dot}\n {caption !== undefined && <span className={styles.caption}>{caption}</span>}\n </div>\n );\n}\n"],"mappings":";;;;AAiCA,SAAgB,EAAQ,EACpB,UAAO,MACP,cACA,WAAQ,cACR,YACA,aAAU,MACG;CACb,IAAM,IAAM,kBAAC,QAAD;EAAM,eAAA;EAAY,WAAW,EAAG,EAAO,SAAS,EAAO,EAAK;CAAI,CAAA;CAY5E,OAVI,CAAC,KAAW,MAAY,KAAA,IAEpB,kBAAC,QAAD;EACI,MAAK;EACL,cAAY;EACZ,WAAW,EAAG,EAAO,SAAS,EAAO,IAAO,CAAS;CACxD,CAAA,IAKL,kBAAC,OAAD;EACI,MAAK;EACL,cAAY;EACZ,aAAU;EACV,WAAW,EAAG,EAAO,MAAM,KAAW,EAAO,SAAS,CAAS;EAJnE,UAAA,CAMK,GACA,MAAY,KAAA,KAAa,kBAAC,QAAD;GAAM,WAAW,EAAO;GAAU,UAAA;EAAc,CAAA,CACzE;;AAEb"}
@@ -1 +1 @@
1
- {"version":3,"file":"Stat.cjs","names":[],"sources":["../../../src/components/Stat/Stat.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Stat.module.css\";\n\nexport type StatTrend = \"up\" | \"down\" | \"flat\";\n\nexport interface StatProps extends HTMLAttributes<HTMLDivElement> {\n /** Metric label (e.g. \"Revenue\", \"Active users\"). */\n label: ReactNode;\n /** Metric value (e.g. \"R$ 12.345\", \"1.2k\"). */\n value: ReactNode;\n /** Optional comparison delta — when set, renders alongside the value. */\n delta?: ReactNode;\n /** Trend direction for the delta. Default inferred from delta string. */\n trend?: StatTrend;\n /** Optional supporting context line below the value. */\n hint?: ReactNode;\n /** Optional leading icon. */\n icon?: ReactNode;\n}\n\nfunction inferTrend(delta: ReactNode | undefined): StatTrend | undefined {\n if (typeof delta !== \"string\") return undefined;\n const trimmed = delta.trim();\n if (trimmed.startsWith(\"+\")) return \"up\";\n if (trimmed.startsWith(\"-\") || trimmed.startsWith(\"−\")) return \"down\";\n return undefined;\n}\n\n/**\n * KPI card. Dashboard widget showing a label + big value + optional\n * delta/trend and hint.\n *\n * @example\n * <Stat label=\"Receita\" value=\"R$ 12.345\" delta=\"+12,4%\" trend=\"up\" hint=\"vs. mês anterior\" />\n */\nexport function Stat({ label, value, delta, trend, hint, icon, className, ...props }: StatProps) {\n const resolvedTrend: StatTrend | undefined = trend ?? inferTrend(delta);\n return (\n <div className={cn(styles.stat, className)} {...props}>\n <div className={styles.header}>\n {icon && <span className={styles.icon}>{icon}</span>}\n <span className={styles.label}>{label}</span>\n </div>\n <div className={styles.row}>\n <span className={styles.value}>{value}</span>\n {delta !== undefined && (\n <span\n className={cn(\n styles.delta,\n resolvedTrend === \"up\" && styles.up,\n resolvedTrend === \"down\" && styles.down,\n resolvedTrend === \"flat\" && styles.flat,\n )}\n >\n {delta}\n </span>\n )}\n </div>\n {hint && <p className={styles.hint}>{hint}</p>}\n </div>\n );\n}\n"],"mappings":"wGAqBA,SAAS,EAAW,EAAqD,CACrE,GAAI,OAAO,GAAU,SAAU,OAC/B,IAAM,EAAU,EAAM,KAAK,EAC3B,GAAI,EAAQ,WAAW,GAAG,EAAG,MAAO,KACpC,GAAI,EAAQ,WAAW,GAAG,GAAK,EAAQ,WAAW,GAAG,EAAG,MAAO,MAEnE,CASA,SAAgB,EAAK,CAAE,QAAO,QAAO,QAAO,QAAO,OAAM,OAAM,YAAW,GAAG,GAAoB,CAC7F,IAAM,EAAuC,GAAS,EAAW,CAAK,EACtE,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,CAAS,EAAG,GAAI,WAAhD,EACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,gBAAvB,CACK,IAAQ,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,cAAO,CAAW,CAAA,GACnD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,eAAQ,CAAY,CAAA,CAC3C,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,aAAvB,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,eAAQ,CAAY,CAAA,EAC3C,IAAU,IAAA,KACP,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,UAAW,EAAA,GACP,EAAA,QAAO,MACP,IAAkB,MAAQ,EAAA,QAAO,GACjC,IAAkB,QAAU,EAAA,QAAO,KACnC,IAAkB,QAAU,EAAA,QAAO,IACvC,WAEC,CACC,CAAA,CAET,IACJ,IAAQ,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAA,QAAO,cAAO,CAAQ,CAAA,CAC5C,GAEb"}
1
+ {"version":3,"file":"Stat.cjs","names":[],"sources":["../../../src/components/Stat/Stat.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Stat.module.css\";\n\nexport type StatTrend = \"up\" | \"down\" | \"flat\";\n\nexport interface StatProps extends HTMLAttributes<HTMLDivElement> {\n /** Metric label (e.g. \"Revenue\", \"Active users\"). */\n label: ReactNode;\n /** Metric value (e.g. \"R$ 12.345\", \"1.2k\"). */\n value: ReactNode;\n /** Optional comparison delta — when set, renders alongside the value. */\n delta?: ReactNode;\n /** Trend direction for the delta. Default inferred from delta string. */\n trend?: StatTrend;\n /** Optional supporting context line below the value. */\n hint?: ReactNode;\n /** Optional leading icon. */\n icon?: ReactNode;\n}\n\nfunction inferTrend(delta: ReactNode | undefined): StatTrend | undefined {\n if (typeof delta !== \"string\") return undefined;\n const trimmed = delta.trim();\n if (trimmed.startsWith(\"+\")) return \"up\";\n if (trimmed.startsWith(\"-\") || trimmed.startsWith(\"−\")) return \"down\";\n return undefined;\n}\n\n/**\n * KPI card. Dashboard widget showing a label + big value + optional\n * delta/trend and hint.\n *\n * @example\n * <Stat label=\"Receita\" value=\"R$ 12.345\" delta=\"+12,4%\" trend=\"up\" hint=\"vs. mês anterior\" />\n */\nexport function Stat({ label, value, delta, trend, hint, icon, className, ...props }: StatProps) {\n const resolvedTrend: StatTrend | undefined = trend ?? inferTrend(delta);\n return (\n <div className={cn(styles.stat, className)} {...props}>\n <div className={styles.header}>\n {icon && <span className={styles.icon}>{icon}</span>}\n <span className={styles.label}>{label}</span>\n </div>\n <div className={styles.row}>\n <span className={styles.value}>{value}</span>\n {delta !== undefined && (\n <span\n className={cn(\n styles.delta,\n resolvedTrend === \"up\" && styles.up,\n resolvedTrend === \"down\" && styles.down,\n resolvedTrend === \"flat\" && styles.flat,\n )}\n >\n {delta}\n </span>\n )}\n </div>\n {hint && <p className={styles.hint}>{hint}</p>}\n </div>\n );\n}\n"],"mappings":"wGAqBA,SAAS,EAAW,EAAqD,CACrE,GAAI,OAAO,GAAU,SAAU,OAC/B,IAAM,EAAU,EAAM,KAAK,EAC3B,GAAI,EAAQ,WAAW,GAAG,EAAG,MAAO,KACpC,GAAI,EAAQ,WAAW,GAAG,GAAK,EAAQ,WAAW,GAAG,EAAG,MAAO,MAEnE,CASA,SAAgB,EAAK,CAAE,QAAO,QAAO,QAAO,QAAO,OAAM,OAAM,YAAW,GAAG,GAAoB,CAC7F,IAAM,EAAuC,GAAS,EAAW,CAAK,EACtE,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,CAAS,EAAG,GAAI,EAAhD,SAAA,EACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,OAAvB,SAAA,CACK,IAAQ,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,KAAO,SAAA,CAAW,CAAA,GACnD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAY,CAAA,CAC3C,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,IAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAY,CAAA,EAC3C,IAAU,IAAA,KACP,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,UAAW,EAAA,GACP,EAAA,QAAO,MACP,IAAkB,MAAQ,EAAA,QAAO,GACjC,IAAkB,QAAU,EAAA,QAAO,KACnC,IAAkB,QAAU,EAAA,QAAO,IACvC,EAEC,SAAA,CACC,CAAA,CAET,IACJ,IAAQ,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAA,QAAO,KAAO,SAAA,CAAQ,CAAA,CAC5C,GAEb"}
@@ -1 +1 @@
1
- {"version":3,"file":"Stat.js","names":[],"sources":["../../../src/components/Stat/Stat.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Stat.module.css\";\n\nexport type StatTrend = \"up\" | \"down\" | \"flat\";\n\nexport interface StatProps extends HTMLAttributes<HTMLDivElement> {\n /** Metric label (e.g. \"Revenue\", \"Active users\"). */\n label: ReactNode;\n /** Metric value (e.g. \"R$ 12.345\", \"1.2k\"). */\n value: ReactNode;\n /** Optional comparison delta — when set, renders alongside the value. */\n delta?: ReactNode;\n /** Trend direction for the delta. Default inferred from delta string. */\n trend?: StatTrend;\n /** Optional supporting context line below the value. */\n hint?: ReactNode;\n /** Optional leading icon. */\n icon?: ReactNode;\n}\n\nfunction inferTrend(delta: ReactNode | undefined): StatTrend | undefined {\n if (typeof delta !== \"string\") return undefined;\n const trimmed = delta.trim();\n if (trimmed.startsWith(\"+\")) return \"up\";\n if (trimmed.startsWith(\"-\") || trimmed.startsWith(\"−\")) return \"down\";\n return undefined;\n}\n\n/**\n * KPI card. Dashboard widget showing a label + big value + optional\n * delta/trend and hint.\n *\n * @example\n * <Stat label=\"Receita\" value=\"R$ 12.345\" delta=\"+12,4%\" trend=\"up\" hint=\"vs. mês anterior\" />\n */\nexport function Stat({ label, value, delta, trend, hint, icon, className, ...props }: StatProps) {\n const resolvedTrend: StatTrend | undefined = trend ?? inferTrend(delta);\n return (\n <div className={cn(styles.stat, className)} {...props}>\n <div className={styles.header}>\n {icon && <span className={styles.icon}>{icon}</span>}\n <span className={styles.label}>{label}</span>\n </div>\n <div className={styles.row}>\n <span className={styles.value}>{value}</span>\n {delta !== undefined && (\n <span\n className={cn(\n styles.delta,\n resolvedTrend === \"up\" && styles.up,\n resolvedTrend === \"down\" && styles.down,\n resolvedTrend === \"flat\" && styles.flat,\n )}\n >\n {delta}\n </span>\n )}\n </div>\n {hint && <p className={styles.hint}>{hint}</p>}\n </div>\n );\n}\n"],"mappings":";;;;AAqBA,SAAS,EAAW,GAAqD;CACrE,IAAI,OAAO,KAAU,UAAU;CAC/B,IAAM,IAAU,EAAM,KAAK;CAC3B,IAAI,EAAQ,WAAW,GAAG,GAAG,OAAO;CACpC,IAAI,EAAQ,WAAW,GAAG,KAAK,EAAQ,WAAW,GAAG,GAAG,OAAO;AAEnE;AASA,SAAgB,EAAK,EAAE,UAAO,UAAO,UAAO,UAAO,SAAM,SAAM,cAAW,GAAG,KAAoB;CAC7F,IAAM,IAAuC,KAAS,EAAW,CAAK;CACtE,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,MAAM,CAAS;EAAG,GAAI;YAAhD;GACI,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB,CACK,KAAQ,kBAAC,QAAD;KAAM,WAAW,EAAO;eAAO;IAAW,CAAA,GACnD,kBAAC,QAAD;KAAM,WAAW,EAAO;eAAQ;IAAY,CAAA,CAC3C;;GACL,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB,CACI,kBAAC,QAAD;KAAM,WAAW,EAAO;eAAQ;IAAY,CAAA,GAC3C,MAAU,KAAA,KACP,kBAAC,QAAD;KACI,WAAW,EACP,EAAO,OACP,MAAkB,QAAQ,EAAO,IACjC,MAAkB,UAAU,EAAO,MACnC,MAAkB,UAAU,EAAO,IACvC;eAEC;IACC,CAAA,CAET;;GACJ,KAAQ,kBAAC,KAAD;IAAG,WAAW,EAAO;cAAO;GAAQ,CAAA;EAC5C;;AAEb"}
1
+ {"version":3,"file":"Stat.js","names":[],"sources":["../../../src/components/Stat/Stat.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Stat.module.css\";\n\nexport type StatTrend = \"up\" | \"down\" | \"flat\";\n\nexport interface StatProps extends HTMLAttributes<HTMLDivElement> {\n /** Metric label (e.g. \"Revenue\", \"Active users\"). */\n label: ReactNode;\n /** Metric value (e.g. \"R$ 12.345\", \"1.2k\"). */\n value: ReactNode;\n /** Optional comparison delta — when set, renders alongside the value. */\n delta?: ReactNode;\n /** Trend direction for the delta. Default inferred from delta string. */\n trend?: StatTrend;\n /** Optional supporting context line below the value. */\n hint?: ReactNode;\n /** Optional leading icon. */\n icon?: ReactNode;\n}\n\nfunction inferTrend(delta: ReactNode | undefined): StatTrend | undefined {\n if (typeof delta !== \"string\") return undefined;\n const trimmed = delta.trim();\n if (trimmed.startsWith(\"+\")) return \"up\";\n if (trimmed.startsWith(\"-\") || trimmed.startsWith(\"−\")) return \"down\";\n return undefined;\n}\n\n/**\n * KPI card. Dashboard widget showing a label + big value + optional\n * delta/trend and hint.\n *\n * @example\n * <Stat label=\"Receita\" value=\"R$ 12.345\" delta=\"+12,4%\" trend=\"up\" hint=\"vs. mês anterior\" />\n */\nexport function Stat({ label, value, delta, trend, hint, icon, className, ...props }: StatProps) {\n const resolvedTrend: StatTrend | undefined = trend ?? inferTrend(delta);\n return (\n <div className={cn(styles.stat, className)} {...props}>\n <div className={styles.header}>\n {icon && <span className={styles.icon}>{icon}</span>}\n <span className={styles.label}>{label}</span>\n </div>\n <div className={styles.row}>\n <span className={styles.value}>{value}</span>\n {delta !== undefined && (\n <span\n className={cn(\n styles.delta,\n resolvedTrend === \"up\" && styles.up,\n resolvedTrend === \"down\" && styles.down,\n resolvedTrend === \"flat\" && styles.flat,\n )}\n >\n {delta}\n </span>\n )}\n </div>\n {hint && <p className={styles.hint}>{hint}</p>}\n </div>\n );\n}\n"],"mappings":";;;;AAqBA,SAAS,EAAW,GAAqD;CACrE,IAAI,OAAO,KAAU,UAAU;CAC/B,IAAM,IAAU,EAAM,KAAK;CAC3B,IAAI,EAAQ,WAAW,GAAG,GAAG,OAAO;CACpC,IAAI,EAAQ,WAAW,GAAG,KAAK,EAAQ,WAAW,GAAG,GAAG,OAAO;AAEnE;AASA,SAAgB,EAAK,EAAE,UAAO,UAAO,UAAO,UAAO,SAAM,SAAM,cAAW,GAAG,KAAoB;CAC7F,IAAM,IAAuC,KAAS,EAAW,CAAK;CACtE,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,MAAM,CAAS;EAAG,GAAI;EAAhD,UAAA;GACI,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAvB,UAAA,CACK,KAAQ,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAO,UAAA;IAAW,CAAA,GACnD,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAQ,UAAA;IAAY,CAAA,CAC3C;;GACL,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAvB,UAAA,CACI,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAQ,UAAA;IAAY,CAAA,GAC3C,MAAU,KAAA,KACP,kBAAC,QAAD;KACI,WAAW,EACP,EAAO,OACP,MAAkB,QAAQ,EAAO,IACjC,MAAkB,UAAU,EAAO,MACnC,MAAkB,UAAU,EAAO,IACvC;KAEC,UAAA;IACC,CAAA,CAET;;GACJ,KAAQ,kBAAC,KAAD;IAAG,WAAW,EAAO;IAAO,UAAA;GAAQ,CAAA;EAC5C;;AAEb"}
@@ -1 +1 @@
1
- {"version":3,"file":"Stepper.cjs","names":[],"sources":["../../../src/components/Stepper/Stepper.tsx"],"sourcesContent":["import { Fragment } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Stepper.module.css\";\n\nexport interface StepItem {\n label: ReactNode;\n /** Secondary line under the label — a hint, or \"optional\". */\n description?: ReactNode;\n}\n\nexport interface StepperProps {\n steps: StepItem[];\n /** Index of the currently active step (0-based). */\n current: number;\n orientation?: \"horizontal\" | \"vertical\";\n /**\n * Makes each step activatable. Without it the steps are a read-only\n * indicator, which is the right default — in a gated flow, jumping ahead\n * would skip the gates.\n */\n onStepClick?: (index: number) => void;\n className?: string;\n}\n\n/**\n * Linear progress indicator for multi-step flows. Steps before `current`\n * render as completed; the step at `current` is active; later steps are\n * upcoming.\n */\nexport function Stepper({\n steps,\n current,\n orientation = \"horizontal\",\n onStepClick,\n className,\n}: StepperProps) {\n return (\n <ol\n className={cn(styles.stepper, orientation === \"vertical\" && styles.vertical, className)}\n >\n {steps.map((step, index) => {\n const completed = index < current;\n const active = index === current;\n return (\n <Fragment key={index}>\n <li\n className={cn(\n styles.step,\n completed && styles.completed,\n active && styles.active,\n )}\n aria-current={active ? \"step\" : undefined}\n >\n {onStepClick ? (\n <button\n type=\"button\"\n className={styles.trigger}\n aria-current={active ? \"step\" : undefined}\n onClick={() => onStepClick(index)}\n >\n <span className={styles.dot}>\n {completed ? \"✓\" : index + 1}\n </span>\n <span className={styles.labelGroup}>\n <span className={styles.label}>{step.label}</span>\n {step.description ? (\n <span className={styles.description}>\n {step.description}\n </span>\n ) : null}\n </span>\n </button>\n ) : (\n <>\n <span className={styles.dot}>\n {completed ? \"✓\" : index + 1}\n </span>\n <span className={styles.labelGroup}>\n <span className={styles.label}>{step.label}</span>\n {step.description ? (\n <span className={styles.description}>\n {step.description}\n </span>\n ) : null}\n </span>\n </>\n )}\n </li>\n {index < steps.length - 1 && (\n <span\n className={cn(styles.connector, completed && styles.completed)}\n aria-hidden\n />\n )}\n </Fragment>\n );\n })}\n </ol>\n );\n}\n"],"mappings":"8HA8BA,SAAgB,EAAQ,CACpB,QACA,UACA,cAAc,aACd,cACA,aACa,CACb,OACI,EAAA,EAAA,IAAA,CAAC,KAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,IAAgB,YAAc,EAAA,QAAO,SAAU,CAAS,WAErF,EAAM,KAAK,EAAM,IAAU,CACxB,IAAM,EAAY,EAAQ,EACpB,EAAS,IAAU,EACzB,OACI,EAAA,EAAA,KAAA,CAAC,EAAA,SAAD,CAAA,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,KAAD,CACI,UAAW,EAAA,GACP,EAAA,QAAO,KACP,GAAa,EAAA,QAAO,UACpB,GAAU,EAAA,QAAO,MACrB,EACA,eAAc,EAAS,OAAS,IAAA,YAE/B,GACG,EAAA,EAAA,KAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,QAClB,eAAc,EAAS,OAAS,IAAA,GAChC,YAAe,EAAY,CAAK,WAJpC,EAMI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,aACnB,EAAY,IAAM,EAAQ,CACzB,CAAA,GACN,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,oBAAxB,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,eAAQ,EAAK,KAAY,CAAA,EAChD,EAAK,aACF,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,qBACnB,EAAK,WACJ,CAAA,EACN,IACF,GACF,KAER,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,aACnB,EAAY,IAAM,EAAQ,CACzB,CAAA,GACN,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,oBAAxB,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,eAAQ,EAAK,KAAY,CAAA,EAChD,EAAK,aACF,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,qBACnB,EAAK,WACJ,CAAA,EACN,IACF,GACR,CAAA,CAAA,CAEN,CAAA,EACH,EAAQ,EAAM,OAAS,IACpB,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,UAAW,GAAa,EAAA,QAAO,SAAS,EAC7D,cAAA,EACH,CAAA,CAEC,CAAA,EAlDK,CAkDL,CAElB,CAAC,CACD,CAAA,CAEZ"}
1
+ {"version":3,"file":"Stepper.cjs","names":[],"sources":["../../../src/components/Stepper/Stepper.tsx"],"sourcesContent":["import { Fragment } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Stepper.module.css\";\n\nexport interface StepItem {\n label: ReactNode;\n /** Secondary line under the label — a hint, or \"optional\". */\n description?: ReactNode;\n}\n\nexport interface StepperProps {\n steps: StepItem[];\n /** Index of the currently active step (0-based). */\n current: number;\n orientation?: \"horizontal\" | \"vertical\";\n /**\n * Makes each step activatable. Without it the steps are a read-only\n * indicator, which is the right default — in a gated flow, jumping ahead\n * would skip the gates.\n */\n onStepClick?: (index: number) => void;\n className?: string;\n}\n\n/**\n * Linear progress indicator for multi-step flows. Steps before `current`\n * render as completed; the step at `current` is active; later steps are\n * upcoming.\n */\nexport function Stepper({\n steps,\n current,\n orientation = \"horizontal\",\n onStepClick,\n className,\n}: StepperProps) {\n return (\n <ol\n className={cn(styles.stepper, orientation === \"vertical\" && styles.vertical, className)}\n >\n {steps.map((step, index) => {\n const completed = index < current;\n const active = index === current;\n return (\n <Fragment key={index}>\n <li\n className={cn(\n styles.step,\n completed && styles.completed,\n active && styles.active,\n )}\n aria-current={active ? \"step\" : undefined}\n >\n {onStepClick ? (\n <button\n type=\"button\"\n className={styles.trigger}\n aria-current={active ? \"step\" : undefined}\n onClick={() => onStepClick(index)}\n >\n <span className={styles.dot}>\n {completed ? \"✓\" : index + 1}\n </span>\n <span className={styles.labelGroup}>\n <span className={styles.label}>{step.label}</span>\n {step.description ? (\n <span className={styles.description}>\n {step.description}\n </span>\n ) : null}\n </span>\n </button>\n ) : (\n <>\n <span className={styles.dot}>\n {completed ? \"✓\" : index + 1}\n </span>\n <span className={styles.labelGroup}>\n <span className={styles.label}>{step.label}</span>\n {step.description ? (\n <span className={styles.description}>\n {step.description}\n </span>\n ) : null}\n </span>\n </>\n )}\n </li>\n {index < steps.length - 1 && (\n <span\n className={cn(styles.connector, completed && styles.completed)}\n aria-hidden\n />\n )}\n </Fragment>\n );\n })}\n </ol>\n );\n}\n"],"mappings":"8HA8BA,SAAgB,EAAQ,CACpB,QACA,UACA,cAAc,aACd,cACA,aACa,CACb,OACI,EAAA,EAAA,IAAA,CAAC,KAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,IAAgB,YAAc,EAAA,QAAO,SAAU,CAAS,EAErF,SAAA,EAAM,KAAK,EAAM,IAAU,CACxB,IAAM,EAAY,EAAQ,EACpB,EAAS,IAAU,EACzB,OACI,EAAA,EAAA,KAAA,CAAC,EAAA,SAAD,CAAA,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,KAAD,CACI,UAAW,EAAA,GACP,EAAA,QAAO,KACP,GAAa,EAAA,QAAO,UACpB,GAAU,EAAA,QAAO,MACrB,EACA,eAAc,EAAS,OAAS,IAAA,GAE/B,SAAA,GACG,EAAA,EAAA,KAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,QAClB,eAAc,EAAS,OAAS,IAAA,GAChC,YAAe,EAAY,CAAK,EAJpC,SAAA,EAMI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,IACnB,SAAA,EAAY,IAAM,EAAQ,CACzB,CAAA,GACN,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,WAAxB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,EAAK,KAAY,CAAA,EAChD,EAAK,aACF,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,YACnB,SAAA,EAAK,WACJ,CAAA,EACN,IACF,CACF,CAAA,CAAA,CAER,CAAA,GAAA,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,IACnB,SAAA,EAAY,IAAM,EAAQ,CACzB,CAAA,GACN,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,WAAxB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,EAAK,KAAY,CAAA,EAChD,EAAK,aACF,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,YACnB,SAAA,EAAK,WACJ,CAAA,EACN,IACF,CACR,CAAA,CAAA,CAAA,CAAA,CAEN,CAAA,EACH,EAAQ,EAAM,OAAS,IACpB,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,UAAW,EAAA,GAAG,EAAA,QAAO,UAAW,GAAa,EAAA,QAAO,SAAS,EAC7D,cAAA,EACH,CAAA,CAEC,CAAA,EAlDK,CAkDL,CAElB,CAAC,CACD,CAAA,CAEZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"Stepper.js","names":[],"sources":["../../../src/components/Stepper/Stepper.tsx"],"sourcesContent":["import { Fragment } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Stepper.module.css\";\n\nexport interface StepItem {\n label: ReactNode;\n /** Secondary line under the label — a hint, or \"optional\". */\n description?: ReactNode;\n}\n\nexport interface StepperProps {\n steps: StepItem[];\n /** Index of the currently active step (0-based). */\n current: number;\n orientation?: \"horizontal\" | \"vertical\";\n /**\n * Makes each step activatable. Without it the steps are a read-only\n * indicator, which is the right default — in a gated flow, jumping ahead\n * would skip the gates.\n */\n onStepClick?: (index: number) => void;\n className?: string;\n}\n\n/**\n * Linear progress indicator for multi-step flows. Steps before `current`\n * render as completed; the step at `current` is active; later steps are\n * upcoming.\n */\nexport function Stepper({\n steps,\n current,\n orientation = \"horizontal\",\n onStepClick,\n className,\n}: StepperProps) {\n return (\n <ol\n className={cn(styles.stepper, orientation === \"vertical\" && styles.vertical, className)}\n >\n {steps.map((step, index) => {\n const completed = index < current;\n const active = index === current;\n return (\n <Fragment key={index}>\n <li\n className={cn(\n styles.step,\n completed && styles.completed,\n active && styles.active,\n )}\n aria-current={active ? \"step\" : undefined}\n >\n {onStepClick ? (\n <button\n type=\"button\"\n className={styles.trigger}\n aria-current={active ? \"step\" : undefined}\n onClick={() => onStepClick(index)}\n >\n <span className={styles.dot}>\n {completed ? \"✓\" : index + 1}\n </span>\n <span className={styles.labelGroup}>\n <span className={styles.label}>{step.label}</span>\n {step.description ? (\n <span className={styles.description}>\n {step.description}\n </span>\n ) : null}\n </span>\n </button>\n ) : (\n <>\n <span className={styles.dot}>\n {completed ? \"✓\" : index + 1}\n </span>\n <span className={styles.labelGroup}>\n <span className={styles.label}>{step.label}</span>\n {step.description ? (\n <span className={styles.description}>\n {step.description}\n </span>\n ) : null}\n </span>\n </>\n )}\n </li>\n {index < steps.length - 1 && (\n <span\n className={cn(styles.connector, completed && styles.completed)}\n aria-hidden\n />\n )}\n </Fragment>\n );\n })}\n </ol>\n );\n}\n"],"mappings":";;;;;AA8BA,SAAgB,EAAQ,EACpB,UACA,YACA,iBAAc,cACd,gBACA,gBACa;CACb,OACI,kBAAC,MAAD;EACI,WAAW,EAAG,EAAO,SAAS,MAAgB,cAAc,EAAO,UAAU,CAAS;YAErF,EAAM,KAAK,GAAM,MAAU;GACxB,IAAM,IAAY,IAAQ,GACpB,IAAS,MAAU;GACzB,OACI,kBAAC,GAAD,EAAA,UAAA,CACI,kBAAC,MAAD;IACI,WAAW,EACP,EAAO,MACP,KAAa,EAAO,WACpB,KAAU,EAAO,MACrB;IACA,gBAAc,IAAS,SAAS,KAAA;cAE/B,IACG,kBAAC,UAAD;KACI,MAAK;KACL,WAAW,EAAO;KAClB,gBAAc,IAAS,SAAS,KAAA;KAChC,eAAe,EAAY,CAAK;eAJpC,CAMI,kBAAC,QAAD;MAAM,WAAW,EAAO;gBACnB,IAAY,MAAM,IAAQ;KACzB,CAAA,GACN,kBAAC,QAAD;MAAM,WAAW,EAAO;gBAAxB,CACI,kBAAC,QAAD;OAAM,WAAW,EAAO;iBAAQ,EAAK;MAAY,CAAA,GAChD,EAAK,cACF,kBAAC,QAAD;OAAM,WAAW,EAAO;iBACnB,EAAK;MACJ,CAAA,IACN,IACF;OACF;SAER,kBAAA,GAAA,EAAA,UAAA,CACI,kBAAC,QAAD;KAAM,WAAW,EAAO;eACnB,IAAY,MAAM,IAAQ;IACzB,CAAA,GACN,kBAAC,QAAD;KAAM,WAAW,EAAO;eAAxB,CACI,kBAAC,QAAD;MAAM,WAAW,EAAO;gBAAQ,EAAK;KAAY,CAAA,GAChD,EAAK,cACF,kBAAC,QAAD;MAAM,WAAW,EAAO;gBACnB,EAAK;KACJ,CAAA,IACN,IACF;MACR,EAAA,CAAA;GAEN,CAAA,GACH,IAAQ,EAAM,SAAS,KACpB,kBAAC,QAAD;IACI,WAAW,EAAG,EAAO,WAAW,KAAa,EAAO,SAAS;IAC7D,eAAA;GACH,CAAA,CAEC,EAAA,GAlDK,CAkDL;EAElB,CAAC;CACD,CAAA;AAEZ"}
1
+ {"version":3,"file":"Stepper.js","names":[],"sources":["../../../src/components/Stepper/Stepper.tsx"],"sourcesContent":["import { Fragment } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Stepper.module.css\";\n\nexport interface StepItem {\n label: ReactNode;\n /** Secondary line under the label — a hint, or \"optional\". */\n description?: ReactNode;\n}\n\nexport interface StepperProps {\n steps: StepItem[];\n /** Index of the currently active step (0-based). */\n current: number;\n orientation?: \"horizontal\" | \"vertical\";\n /**\n * Makes each step activatable. Without it the steps are a read-only\n * indicator, which is the right default — in a gated flow, jumping ahead\n * would skip the gates.\n */\n onStepClick?: (index: number) => void;\n className?: string;\n}\n\n/**\n * Linear progress indicator for multi-step flows. Steps before `current`\n * render as completed; the step at `current` is active; later steps are\n * upcoming.\n */\nexport function Stepper({\n steps,\n current,\n orientation = \"horizontal\",\n onStepClick,\n className,\n}: StepperProps) {\n return (\n <ol\n className={cn(styles.stepper, orientation === \"vertical\" && styles.vertical, className)}\n >\n {steps.map((step, index) => {\n const completed = index < current;\n const active = index === current;\n return (\n <Fragment key={index}>\n <li\n className={cn(\n styles.step,\n completed && styles.completed,\n active && styles.active,\n )}\n aria-current={active ? \"step\" : undefined}\n >\n {onStepClick ? (\n <button\n type=\"button\"\n className={styles.trigger}\n aria-current={active ? \"step\" : undefined}\n onClick={() => onStepClick(index)}\n >\n <span className={styles.dot}>\n {completed ? \"✓\" : index + 1}\n </span>\n <span className={styles.labelGroup}>\n <span className={styles.label}>{step.label}</span>\n {step.description ? (\n <span className={styles.description}>\n {step.description}\n </span>\n ) : null}\n </span>\n </button>\n ) : (\n <>\n <span className={styles.dot}>\n {completed ? \"✓\" : index + 1}\n </span>\n <span className={styles.labelGroup}>\n <span className={styles.label}>{step.label}</span>\n {step.description ? (\n <span className={styles.description}>\n {step.description}\n </span>\n ) : null}\n </span>\n </>\n )}\n </li>\n {index < steps.length - 1 && (\n <span\n className={cn(styles.connector, completed && styles.completed)}\n aria-hidden\n />\n )}\n </Fragment>\n );\n })}\n </ol>\n );\n}\n"],"mappings":";;;;;AA8BA,SAAgB,EAAQ,EACpB,UACA,YACA,iBAAc,cACd,gBACA,gBACa;CACb,OACI,kBAAC,MAAD;EACI,WAAW,EAAG,EAAO,SAAS,MAAgB,cAAc,EAAO,UAAU,CAAS;EAErF,UAAA,EAAM,KAAK,GAAM,MAAU;GACxB,IAAM,IAAY,IAAQ,GACpB,IAAS,MAAU;GACzB,OACI,kBAAC,GAAD,EAAA,UAAA,CACI,kBAAC,MAAD;IACI,WAAW,EACP,EAAO,MACP,KAAa,EAAO,WACpB,KAAU,EAAO,MACrB;IACA,gBAAc,IAAS,SAAS,KAAA;IAE/B,UAAA,IACG,kBAAC,UAAD;KACI,MAAK;KACL,WAAW,EAAO;KAClB,gBAAc,IAAS,SAAS,KAAA;KAChC,eAAe,EAAY,CAAK;KAJpC,UAAA,CAMI,kBAAC,QAAD;MAAM,WAAW,EAAO;MACnB,UAAA,IAAY,MAAM,IAAQ;KACzB,CAAA,GACN,kBAAC,QAAD;MAAM,WAAW,EAAO;MAAxB,UAAA,CACI,kBAAC,QAAD;OAAM,WAAW,EAAO;OAAQ,UAAA,EAAK;MAAY,CAAA,GAChD,EAAK,cACF,kBAAC,QAAD;OAAM,WAAW,EAAO;OACnB,UAAA,EAAK;MACJ,CAAA,IACN,IACF;KACF,CAAA,CAAA;IAER,CAAA,IAAA,kBAAA,GAAA,EAAA,UAAA,CACI,kBAAC,QAAD;KAAM,WAAW,EAAO;KACnB,UAAA,IAAY,MAAM,IAAQ;IACzB,CAAA,GACN,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAxB,UAAA,CACI,kBAAC,QAAD;MAAM,WAAW,EAAO;MAAQ,UAAA,EAAK;KAAY,CAAA,GAChD,EAAK,cACF,kBAAC,QAAD;MAAM,WAAW,EAAO;MACnB,UAAA,EAAK;KACJ,CAAA,IACN,IACF;IACR,CAAA,CAAA,EAAA,CAAA;GAEN,CAAA,GACH,IAAQ,EAAM,SAAS,KACpB,kBAAC,QAAD;IACI,WAAW,EAAG,EAAO,WAAW,KAAa,EAAO,SAAS;IAC7D,eAAA;GACH,CAAA,CAEC,EAAA,GAlDK,CAkDL;EAElB,CAAC;CACD,CAAA;AAEZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"StepperInput.cjs","names":[],"sources":["../../../src/components/StepperInput/StepperInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — value/onChange/min/max/step is the numeric contract,\n * format renders it, labels names the increment and decrement buttons for screen\n * readers, and size/disabled/label/className are the field. The button labels cannot\n * be defaulted: they are the only text those buttons have.\n */\nimport { forwardRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { clamp } from \"@/utils/numbers\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./StepperInput.module.css\";\n\nexport interface StepperInputProps {\n /** Current value. */\n value: number;\n /** Fires with the new value (already clamped to min/max). */\n onChange: (value: number) => void;\n /** Lower bound. Default `0`. */\n min?: number;\n /** Upper bound. Default `Number.POSITIVE_INFINITY`. */\n max?: number;\n /** Increment per click. Default `1`. */\n step?: number;\n /** Visual size. Default `\"md\"`. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Disable the whole control. */\n disabled?: boolean;\n /** Optional label rendered above. */\n label?: ReactNode;\n /** Optional formatter for the displayed value. */\n format?: (value: number) => string;\n /** Custom button labels for accessibility. */\n labels?: { decrement: string; increment: string };\n className?: string;\n}\n\n/**\n * Numeric +/− stepper. Common in checkout quantity selectors and admin\n * forms. Clamps to `[min, max]` and emits already-bounded values.\n *\n * @example\n * <StepperInput value={qty} onChange={setQty} min={1} max={10} />\n */\nexport const StepperInput = forwardRef<HTMLDivElement, StepperInputProps>(function StepperInput(\n {\n value,\n onChange,\n min = 0,\n max = Number.POSITIVE_INFINITY,\n step = 1,\n size = \"md\",\n disabled = false,\n label,\n format,\n labels = { decrement: \"Diminuir\", increment: \"Aumentar\" },\n className,\n },\n ref,\n) {\n const decrement = (): void => {\n if (disabled) return;\n onChange(clamp(value - step, min, max));\n };\n const increment = (): void => {\n if (disabled) return;\n onChange(clamp(value + step, min, max));\n };\n\n const display = format ? format(value) : String(value);\n const canDecrement = !disabled && value > min;\n const canIncrement = !disabled && value < max;\n\n return (\n <div ref={ref} className={cn(styles.wrapper, className)}>\n {label && <label className={styles.label}>{label}</label>}\n <div className={cn(styles.row, styles[size], disabled && styles.disabled)}>\n <button\n type=\"button\"\n className={styles.btn}\n aria-label={labels.decrement}\n onClick={decrement}\n disabled={!canDecrement}\n >\n −\n </button>\n <span className={styles.value} role=\"status\" aria-live=\"polite\">\n {display}\n </span>\n <button\n type=\"button\"\n className={styles.btn}\n aria-label={labels.increment}\n onClick={increment}\n disabled={!canIncrement}\n >\n +\n </button>\n </div>\n </div>\n );\n});\n"],"mappings":"wKA2CA,IAAa,GAAA,EAAA,EAAA,WAAA,CAA6D,SACtE,CACI,QACA,WACA,MAAM,EACN,MAAM,IACN,OAAO,EACP,OAAO,KACP,WAAW,GACX,QACA,SACA,SAAS,CAAE,UAAW,WAAY,UAAW,UAAW,EACxD,aAEJ,EACF,CACE,IAAM,MAAwB,CACtB,GACJ,EAAS,EAAA,MAAM,EAAQ,EAAM,EAAK,CAAG,CAAC,CAC1C,EACM,MAAwB,CACtB,GACJ,EAAS,EAAA,MAAM,EAAQ,EAAM,EAAK,CAAG,CAAC,CAC1C,EAEM,EAAU,EAAS,EAAO,CAAK,EAAI,OAAO,CAAK,EAC/C,EAAe,CAAC,GAAY,EAAQ,EACpC,EAAe,CAAC,GAAY,EAAQ,EAE1C,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAU,MAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,WAAtD,CACK,IAAS,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,UAAW,EAAA,QAAO,eAAQ,CAAa,CAAA,GACxD,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,IAAK,EAAA,QAAO,GAAO,GAAY,EAAA,QAAO,QAAQ,WAAxE,EACI,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,IAClB,aAAY,EAAO,UACnB,QAAS,EACT,SAAU,CAAC,WACd,GAEO,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAO,KAAK,SAAS,YAAU,kBAClD,CACC,CAAA,GACN,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,IAClB,aAAY,EAAO,UACnB,QAAS,EACT,SAAU,CAAC,WACd,GAEO,CAAA,CACP,GACJ,GAEb,CAAC"}
1
+ {"version":3,"file":"StepperInput.cjs","names":[],"sources":["../../../src/components/StepperInput/StepperInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — value/onChange/min/max/step is the numeric contract,\n * format renders it, labels names the increment and decrement buttons for screen\n * readers, and size/disabled/label/className are the field. The button labels cannot\n * be defaulted: they are the only text those buttons have.\n */\nimport { forwardRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { clamp } from \"@/utils/numbers\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./StepperInput.module.css\";\n\nexport interface StepperInputProps {\n /** Current value. */\n value: number;\n /** Fires with the new value (already clamped to min/max). */\n onChange: (value: number) => void;\n /** Lower bound. Default `0`. */\n min?: number;\n /** Upper bound. Default `Number.POSITIVE_INFINITY`. */\n max?: number;\n /** Increment per click. Default `1`. */\n step?: number;\n /** Visual size. Default `\"md\"`. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Disable the whole control. */\n disabled?: boolean;\n /** Optional label rendered above. */\n label?: ReactNode;\n /** Optional formatter for the displayed value. */\n format?: (value: number) => string;\n /** Custom button labels for accessibility. */\n labels?: { decrement: string; increment: string };\n className?: string;\n}\n\n/**\n * Numeric +/− stepper. Common in checkout quantity selectors and admin\n * forms. Clamps to `[min, max]` and emits already-bounded values.\n *\n * @example\n * <StepperInput value={qty} onChange={setQty} min={1} max={10} />\n */\nexport const StepperInput = forwardRef<HTMLDivElement, StepperInputProps>(function StepperInput(\n {\n value,\n onChange,\n min = 0,\n max = Number.POSITIVE_INFINITY,\n step = 1,\n size = \"md\",\n disabled = false,\n label,\n format,\n labels = { decrement: \"Diminuir\", increment: \"Aumentar\" },\n className,\n },\n ref,\n) {\n const decrement = (): void => {\n if (disabled) return;\n onChange(clamp(value - step, min, max));\n };\n const increment = (): void => {\n if (disabled) return;\n onChange(clamp(value + step, min, max));\n };\n\n const display = format ? format(value) : String(value);\n const canDecrement = !disabled && value > min;\n const canIncrement = !disabled && value < max;\n\n return (\n <div ref={ref} className={cn(styles.wrapper, className)}>\n {label && <label className={styles.label}>{label}</label>}\n <div className={cn(styles.row, styles[size], disabled && styles.disabled)}>\n <button\n type=\"button\"\n className={styles.btn}\n aria-label={labels.decrement}\n onClick={decrement}\n disabled={!canDecrement}\n >\n −\n </button>\n <span className={styles.value} role=\"status\" aria-live=\"polite\">\n {display}\n </span>\n <button\n type=\"button\"\n className={styles.btn}\n aria-label={labels.increment}\n onClick={increment}\n disabled={!canIncrement}\n >\n +\n </button>\n </div>\n </div>\n );\n});\n"],"mappings":"wKA2CA,IAAa,GAAA,EAAe,EAAA,WAAA,CAA8C,SACtE,CACI,QACA,WACA,MAAM,EACN,MAAM,IACN,OAAO,EACP,OAAO,KACP,WAAW,GACX,QACA,SACA,SAAS,CAAE,UAAW,WAAY,UAAW,UAAW,EACxD,aAEJ,EACF,CACE,IAAM,MAAwB,CACtB,GACJ,EAAS,EAAA,MAAM,EAAQ,EAAM,EAAK,CAAG,CAAC,CAC1C,EACM,MAAwB,CACtB,GACJ,EAAS,EAAA,MAAM,EAAQ,EAAM,EAAK,CAAG,CAAC,CAC1C,EAEM,EAAU,EAAS,EAAO,CAAK,EAAI,OAAO,CAAK,EAC/C,EAAe,CAAC,GAAY,EAAQ,EACpC,EAAe,CAAC,GAAY,EAAQ,EAE1C,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAU,MAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EAAtD,SAAA,CACK,IAAS,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAa,CAAA,GACxD,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,IAAK,EAAA,QAAO,GAAO,GAAY,EAAA,QAAO,QAAQ,EAAxE,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,IAClB,aAAY,EAAO,UACnB,QAAS,EACT,SAAU,CAAC,EACd,SAAA,GAEO,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAO,KAAK,SAAS,YAAU,SAClD,SAAA,CACC,CAAA,GACN,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,IAClB,aAAY,EAAO,UACnB,QAAS,EACT,SAAU,CAAC,EACd,SAAA,GAEO,CAAA,CACP,CACJ,CAAA,CAAA,GAEb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"StepperInput.js","names":[],"sources":["../../../src/components/StepperInput/StepperInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — value/onChange/min/max/step is the numeric contract,\n * format renders it, labels names the increment and decrement buttons for screen\n * readers, and size/disabled/label/className are the field. The button labels cannot\n * be defaulted: they are the only text those buttons have.\n */\nimport { forwardRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { clamp } from \"@/utils/numbers\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./StepperInput.module.css\";\n\nexport interface StepperInputProps {\n /** Current value. */\n value: number;\n /** Fires with the new value (already clamped to min/max). */\n onChange: (value: number) => void;\n /** Lower bound. Default `0`. */\n min?: number;\n /** Upper bound. Default `Number.POSITIVE_INFINITY`. */\n max?: number;\n /** Increment per click. Default `1`. */\n step?: number;\n /** Visual size. Default `\"md\"`. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Disable the whole control. */\n disabled?: boolean;\n /** Optional label rendered above. */\n label?: ReactNode;\n /** Optional formatter for the displayed value. */\n format?: (value: number) => string;\n /** Custom button labels for accessibility. */\n labels?: { decrement: string; increment: string };\n className?: string;\n}\n\n/**\n * Numeric +/− stepper. Common in checkout quantity selectors and admin\n * forms. Clamps to `[min, max]` and emits already-bounded values.\n *\n * @example\n * <StepperInput value={qty} onChange={setQty} min={1} max={10} />\n */\nexport const StepperInput = forwardRef<HTMLDivElement, StepperInputProps>(function StepperInput(\n {\n value,\n onChange,\n min = 0,\n max = Number.POSITIVE_INFINITY,\n step = 1,\n size = \"md\",\n disabled = false,\n label,\n format,\n labels = { decrement: \"Diminuir\", increment: \"Aumentar\" },\n className,\n },\n ref,\n) {\n const decrement = (): void => {\n if (disabled) return;\n onChange(clamp(value - step, min, max));\n };\n const increment = (): void => {\n if (disabled) return;\n onChange(clamp(value + step, min, max));\n };\n\n const display = format ? format(value) : String(value);\n const canDecrement = !disabled && value > min;\n const canIncrement = !disabled && value < max;\n\n return (\n <div ref={ref} className={cn(styles.wrapper, className)}>\n {label && <label className={styles.label}>{label}</label>}\n <div className={cn(styles.row, styles[size], disabled && styles.disabled)}>\n <button\n type=\"button\"\n className={styles.btn}\n aria-label={labels.decrement}\n onClick={decrement}\n disabled={!canDecrement}\n >\n −\n </button>\n <span className={styles.value} role=\"status\" aria-live=\"polite\">\n {display}\n </span>\n <button\n type=\"button\"\n className={styles.btn}\n aria-label={labels.increment}\n onClick={increment}\n disabled={!canIncrement}\n >\n +\n </button>\n </div>\n </div>\n );\n});\n"],"mappings":";;;;;;AA2CA,IAAa,IAAe,EAA8C,SACtE,EACI,UACA,aACA,SAAM,GACN,SAAM,UACN,UAAO,GACP,UAAO,MACP,cAAW,IACX,UACA,WACA,YAAS;CAAE,WAAW;CAAY,WAAW;AAAW,GACxD,gBAEJ,GACF;CACE,IAAM,UAAwB;EACtB,KACJ,EAAS,EAAM,IAAQ,GAAM,GAAK,CAAG,CAAC;CAC1C,GACM,UAAwB;EACtB,KACJ,EAAS,EAAM,IAAQ,GAAM,GAAK,CAAG,CAAC;CAC1C,GAEM,IAAU,IAAS,EAAO,CAAK,IAAI,OAAO,CAAK,GAC/C,IAAe,CAAC,KAAY,IAAQ,GACpC,IAAe,CAAC,KAAY,IAAQ;CAE1C,OACI,kBAAC,OAAD;EAAU;EAAK,WAAW,EAAG,EAAO,SAAS,CAAS;YAAtD,CACK,KAAS,kBAAC,SAAD;GAAO,WAAW,EAAO;aAAQ;EAAa,CAAA,GACxD,kBAAC,OAAD;GAAK,WAAW,EAAG,EAAO,KAAK,EAAO,IAAO,KAAY,EAAO,QAAQ;aAAxE;IACI,kBAAC,UAAD;KACI,MAAK;KACL,WAAW,EAAO;KAClB,cAAY,EAAO;KACnB,SAAS;KACT,UAAU,CAAC;eACd;IAEO,CAAA;IACR,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAO,MAAK;KAAS,aAAU;eAClD;IACC,CAAA;IACN,kBAAC,UAAD;KACI,MAAK;KACL,WAAW,EAAO;KAClB,cAAY,EAAO;KACnB,SAAS;KACT,UAAU,CAAC;eACd;IAEO,CAAA;GACP;IACJ;;AAEb,CAAC"}
1
+ {"version":3,"file":"StepperInput.js","names":[],"sources":["../../../src/components/StepperInput/StepperInput.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — value/onChange/min/max/step is the numeric contract,\n * format renders it, labels names the increment and decrement buttons for screen\n * readers, and size/disabled/label/className are the field. The button labels cannot\n * be defaulted: they are the only text those buttons have.\n */\nimport { forwardRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { clamp } from \"@/utils/numbers\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./StepperInput.module.css\";\n\nexport interface StepperInputProps {\n /** Current value. */\n value: number;\n /** Fires with the new value (already clamped to min/max). */\n onChange: (value: number) => void;\n /** Lower bound. Default `0`. */\n min?: number;\n /** Upper bound. Default `Number.POSITIVE_INFINITY`. */\n max?: number;\n /** Increment per click. Default `1`. */\n step?: number;\n /** Visual size. Default `\"md\"`. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Disable the whole control. */\n disabled?: boolean;\n /** Optional label rendered above. */\n label?: ReactNode;\n /** Optional formatter for the displayed value. */\n format?: (value: number) => string;\n /** Custom button labels for accessibility. */\n labels?: { decrement: string; increment: string };\n className?: string;\n}\n\n/**\n * Numeric +/− stepper. Common in checkout quantity selectors and admin\n * forms. Clamps to `[min, max]` and emits already-bounded values.\n *\n * @example\n * <StepperInput value={qty} onChange={setQty} min={1} max={10} />\n */\nexport const StepperInput = forwardRef<HTMLDivElement, StepperInputProps>(function StepperInput(\n {\n value,\n onChange,\n min = 0,\n max = Number.POSITIVE_INFINITY,\n step = 1,\n size = \"md\",\n disabled = false,\n label,\n format,\n labels = { decrement: \"Diminuir\", increment: \"Aumentar\" },\n className,\n },\n ref,\n) {\n const decrement = (): void => {\n if (disabled) return;\n onChange(clamp(value - step, min, max));\n };\n const increment = (): void => {\n if (disabled) return;\n onChange(clamp(value + step, min, max));\n };\n\n const display = format ? format(value) : String(value);\n const canDecrement = !disabled && value > min;\n const canIncrement = !disabled && value < max;\n\n return (\n <div ref={ref} className={cn(styles.wrapper, className)}>\n {label && <label className={styles.label}>{label}</label>}\n <div className={cn(styles.row, styles[size], disabled && styles.disabled)}>\n <button\n type=\"button\"\n className={styles.btn}\n aria-label={labels.decrement}\n onClick={decrement}\n disabled={!canDecrement}\n >\n −\n </button>\n <span className={styles.value} role=\"status\" aria-live=\"polite\">\n {display}\n </span>\n <button\n type=\"button\"\n className={styles.btn}\n aria-label={labels.increment}\n onClick={increment}\n disabled={!canIncrement}\n >\n +\n </button>\n </div>\n </div>\n );\n});\n"],"mappings":";;;;;;AA2CA,IAAa,IAAe,EAA8C,SACtE,EACI,UACA,aACA,SAAM,GACN,SAAM,UACN,UAAO,GACP,UAAO,MACP,cAAW,IACX,UACA,WACA,YAAS;CAAE,WAAW;CAAY,WAAW;AAAW,GACxD,gBAEJ,GACF;CACE,IAAM,UAAwB;EACtB,KACJ,EAAS,EAAM,IAAQ,GAAM,GAAK,CAAG,CAAC;CAC1C,GACM,UAAwB;EACtB,KACJ,EAAS,EAAM,IAAQ,GAAM,GAAK,CAAG,CAAC;CAC1C,GAEM,IAAU,IAAS,EAAO,CAAK,IAAI,OAAO,CAAK,GAC/C,IAAe,CAAC,KAAY,IAAQ,GACpC,IAAe,CAAC,KAAY,IAAQ;CAE1C,OACI,kBAAC,OAAD;EAAU;EAAK,WAAW,EAAG,EAAO,SAAS,CAAS;EAAtD,UAAA,CACK,KAAS,kBAAC,SAAD;GAAO,WAAW,EAAO;GAAQ,UAAA;EAAa,CAAA,GACxD,kBAAC,OAAD;GAAK,WAAW,EAAG,EAAO,KAAK,EAAO,IAAO,KAAY,EAAO,QAAQ;GAAxE,UAAA;IACI,kBAAC,UAAD;KACI,MAAK;KACL,WAAW,EAAO;KAClB,cAAY,EAAO;KACnB,SAAS;KACT,UAAU,CAAC;KACd,UAAA;IAEO,CAAA;IACR,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAO,MAAK;KAAS,aAAU;KAClD,UAAA;IACC,CAAA;IACN,kBAAC,UAAD;KACI,MAAK;KACL,WAAW,EAAO;KAClB,cAAY,EAAO;KACnB,SAAS;KACT,UAAU,CAAC;KACd,UAAA;IAEO,CAAA;GACP;EACJ,CAAA,CAAA;;AAEb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.cjs","names":[],"sources":["../../../src/components/Switch/Switch.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Switch.module.css\";\n\nexport interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n label?: ReactNode;\n wrapperClassName?: string;\n}\n\n/** Toggle switch backed by a checkbox input. Accessible via keyboard. */\nexport const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(\n { label, disabled, wrapperClassName, className, ...props },\n ref,\n) {\n return (\n <label className={cn(styles.wrapper, disabled && styles.disabled, wrapperClassName)}>\n <input\n ref={ref}\n type=\"checkbox\"\n role=\"switch\"\n disabled={disabled}\n className={cn(styles.input, className)}\n {...props}\n />\n <span className={styles.track} aria-hidden>\n <span className={styles.thumb} />\n </span>\n {label && <span className={styles.label}>{label}</span>}\n </label>\n );\n});\n"],"mappings":"6HAWA,IAAa,GAAA,EAAA,EAAA,WAAA,CAAmD,SAC5D,CAAE,QAAO,WAAU,mBAAkB,YAAW,GAAG,GACnD,EACF,CACE,OACI,EAAA,EAAA,KAAA,CAAC,QAAD,CAAO,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,GAAY,EAAA,QAAO,SAAU,CAAgB,WAAlF,EACI,EAAA,EAAA,IAAA,CAAC,QAAD,CACS,MACL,KAAK,WACL,KAAK,SACK,WACV,UAAW,EAAA,GAAG,EAAA,QAAO,MAAO,CAAS,EACrC,GAAI,CACP,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAO,cAAA,aAC3B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,KAAQ,CAAA,CAC9B,CAAA,EACL,IAAS,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,eAAQ,CAAY,CAAA,CACnD,GAEf,CAAC"}
1
+ {"version":3,"file":"Switch.cjs","names":[],"sources":["../../../src/components/Switch/Switch.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Switch.module.css\";\n\nexport interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n label?: ReactNode;\n wrapperClassName?: string;\n}\n\n/** Toggle switch backed by a checkbox input. Accessible via keyboard. */\nexport const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(\n { label, disabled, wrapperClassName, className, ...props },\n ref,\n) {\n return (\n <label className={cn(styles.wrapper, disabled && styles.disabled, wrapperClassName)}>\n <input\n ref={ref}\n type=\"checkbox\"\n role=\"switch\"\n disabled={disabled}\n className={cn(styles.input, className)}\n {...props}\n />\n <span className={styles.track} aria-hidden>\n <span className={styles.thumb} />\n </span>\n {label && <span className={styles.label}>{label}</span>}\n </label>\n );\n});\n"],"mappings":"6HAWA,IAAa,GAAA,EAAS,EAAA,WAAA,CAA0C,SAC5D,CAAE,QAAO,WAAU,mBAAkB,YAAW,GAAG,GACnD,EACF,CACE,OACI,EAAA,EAAA,KAAA,CAAC,QAAD,CAAO,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,GAAY,EAAA,QAAO,SAAU,CAAgB,EAAlF,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,QAAD,CACS,MACL,KAAK,WACL,KAAK,SACK,WACV,UAAW,EAAA,GAAG,EAAA,QAAO,MAAO,CAAS,EACrC,GAAI,CACP,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAO,cAAA,GAC3B,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,KAAQ,CAAA,CAC9B,CAAA,EACL,IAAS,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAY,CAAA,CACnD,GAEf,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.js","names":[],"sources":["../../../src/components/Switch/Switch.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Switch.module.css\";\n\nexport interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n label?: ReactNode;\n wrapperClassName?: string;\n}\n\n/** Toggle switch backed by a checkbox input. Accessible via keyboard. */\nexport const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(\n { label, disabled, wrapperClassName, className, ...props },\n ref,\n) {\n return (\n <label className={cn(styles.wrapper, disabled && styles.disabled, wrapperClassName)}>\n <input\n ref={ref}\n type=\"checkbox\"\n role=\"switch\"\n disabled={disabled}\n className={cn(styles.input, className)}\n {...props}\n />\n <span className={styles.track} aria-hidden>\n <span className={styles.thumb} />\n </span>\n {label && <span className={styles.label}>{label}</span>}\n </label>\n );\n});\n"],"mappings":";;;;;AAWA,IAAa,IAAS,EAA0C,SAC5D,EAAE,UAAO,aAAU,qBAAkB,cAAW,GAAG,KACnD,GACF;CACE,OACI,kBAAC,SAAD;EAAO,WAAW,EAAG,EAAO,SAAS,KAAY,EAAO,UAAU,CAAgB;YAAlF;GACI,kBAAC,SAAD;IACS;IACL,MAAK;IACL,MAAK;IACK;IACV,WAAW,EAAG,EAAO,OAAO,CAAS;IACrC,GAAI;GACP,CAAA;GACD,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAO,eAAA;cAC3B,kBAAC,QAAD,EAAM,WAAW,EAAO,MAAQ,CAAA;GAC9B,CAAA;GACL,KAAS,kBAAC,QAAD;IAAM,WAAW,EAAO;cAAQ;GAAY,CAAA;EACnD;;AAEf,CAAC"}
1
+ {"version":3,"file":"Switch.js","names":[],"sources":["../../../src/components/Switch/Switch.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Switch.module.css\";\n\nexport interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n label?: ReactNode;\n wrapperClassName?: string;\n}\n\n/** Toggle switch backed by a checkbox input. Accessible via keyboard. */\nexport const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(\n { label, disabled, wrapperClassName, className, ...props },\n ref,\n) {\n return (\n <label className={cn(styles.wrapper, disabled && styles.disabled, wrapperClassName)}>\n <input\n ref={ref}\n type=\"checkbox\"\n role=\"switch\"\n disabled={disabled}\n className={cn(styles.input, className)}\n {...props}\n />\n <span className={styles.track} aria-hidden>\n <span className={styles.thumb} />\n </span>\n {label && <span className={styles.label}>{label}</span>}\n </label>\n );\n});\n"],"mappings":";;;;;AAWA,IAAa,IAAS,EAA0C,SAC5D,EAAE,UAAO,aAAU,qBAAkB,cAAW,GAAG,KACnD,GACF;CACE,OACI,kBAAC,SAAD;EAAO,WAAW,EAAG,EAAO,SAAS,KAAY,EAAO,UAAU,CAAgB;EAAlF,UAAA;GACI,kBAAC,SAAD;IACS;IACL,MAAK;IACL,MAAK;IACK;IACV,WAAW,EAAG,EAAO,OAAO,CAAS;IACrC,GAAI;GACP,CAAA;GACD,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAO,eAAA;IAC3B,UAAA,kBAAC,QAAD,EAAM,WAAW,EAAO,MAAQ,CAAA;GAC9B,CAAA;GACL,KAAS,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAQ,UAAA;GAAY,CAAA;EACnD;;AAEf,CAAC"}