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
@@ -136,7 +136,7 @@ function y(t, n, r) {
136
136
  let i = {}, a = t[500], o = r === "dark" ? t[900] : t[50], s = r === "dark" ? t[50] : t[900], c = Math.min(_, Math.max(o, n + .05)), l = Math.max(v, Math.min(s, n - .05));
137
137
  for (let r of e) {
138
138
  let e = t[r];
139
- e === a ? i[r] = n : e > a ? i[r] = n + (e - a) / (o - a) * (c - n) : i[r] = n - (a - e) / (a - s) * (n - l);
139
+ i[r] = e === a ? n : e > a ? n + (e - a) / (o - a) * (c - n) : n - (a - e) / (a - s) * (n - l);
140
140
  }
141
141
  return i;
142
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"color.js","names":[],"sources":["../../src/theme/color.ts"],"sourcesContent":["/**\n * @tempest-limits file-lines — OKLCH ↔ sRGB with the gamut mapping in between: the\n * transfer function, the LMS matrices, the chroma search that finds the nearest in-\n * gamut colour and the contrast ratio used to check it. Matrices split across files\n * are matrices that get edited one half at a time.\n */\n/**\n * Color math behind {@link createTheme} — OKLab/OKLCH conversions, tint scale\n * generation and WCAG contrast picking.\n *\n * Everything here is pure and dependency-free: the SDK generates brand ramps at\n * runtime in the browser, so a color library would be a disproportionate cost\n * for ~150 lines of well-specified math. OKLCH is used instead of HSL because\n * HSL lightness is not perceptual — an HSL ramp of a yellow and of a blue at the\n * same `L` read as wildly different brightness, which is exactly what breaks a\n * generated palette.\n */\n\n/** A color in the OKLCH space: perceptual lightness, chroma and hue. */\nexport interface Oklch {\n /** Perceptual lightness, `0` (black) to `1` (white). */\n l: number;\n /** Chroma (colorfulness). `0` is gray; sRGB rarely exceeds `~0.37`. */\n c: number;\n /** Hue angle in degrees, `0`–`360`. */\n h: number;\n}\n\n/** The ten steps of a Tempest tint scale, lightest to darkest. */\nexport type ScaleStep = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;\n\n/** A generated tint scale, keyed by step. */\nexport type ColorScale = Record<ScaleStep, string>;\n\nconst SCALE_STEPS: ScaleStep[] = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];\n\n/**\n * Target lightness per step for a **brand** ramp in light mode.\n *\n * These are the measured OKLCH lightnesses of the hand-written `--tempest-primary-*`\n * scale in `colors.css`, so a generated brand ramp lands in the same visual range\n * as the built-in one instead of merely near it.\n */\nconst LIGHT_LIGHTNESS: Record<ScaleStep, number> = {\n 50: 0.966,\n 100: 0.923,\n 200: 0.844,\n 300: 0.743,\n 400: 0.642,\n 500: 0.563,\n 600: 0.48,\n 700: 0.391,\n 800: 0.325,\n 900: 0.251,\n};\n\n/**\n * Target lightness per step for a **neutral** ramp in light mode — measured from\n * the hand-written `--tempest-gray-*` scale.\n *\n * Deliberately **wider** than the brand curve at both ends (`0.982` → `0.210` vs\n * `0.966` → `0.251`): a neutral carries surfaces that must read as near-white and\n * text that must read as near-black, and the pair `text-muted` on `surface-3` has\n * to clear AA. Reusing the brand curve for neutrals is what dropped that pair to\n * 3.5:1 and made the browser axe sweep fail on every generated theme.\n */\nconst NEUTRAL_LIGHT_LIGHTNESS: Record<ScaleStep, number> = {\n 50: 0.982,\n 100: 0.963,\n 200: 0.927,\n 300: 0.872,\n 400: 0.71,\n 500: 0.544,\n 600: 0.442,\n 700: 0.369,\n 800: 0.278,\n 900: 0.21,\n};\n\n/**\n * Neutral ramp for dark mode, measured from the `[data-tempest-theme=\"dark\"]`\n * surface/text tokens: `50` is the page background and `900` is text-grade.\n */\nconst NEUTRAL_DARK_LIGHTNESS: Record<ScaleStep, number> = {\n 50: 0.159,\n 100: 0.205,\n 200: 0.254,\n 300: 0.314,\n 400: 0.381,\n 500: 0.5,\n 600: 0.571,\n 700: 0.762,\n 800: 0.86,\n 900: 0.964,\n};\n\n/**\n * Target lightness for a dark-theme ramp — the ramp is **inverted**: `50` is the\n * darkest tint (a surface) and `900` the lightest (text-grade), matching the\n * `[data-tempest-theme=\"dark\"]` block in `colors.css`.\n */\nconst DARK_LIGHTNESS: Record<ScaleStep, number> = {\n 50: 0.238,\n 100: 0.288,\n 200: 0.362,\n 300: 0.452,\n 400: 0.544,\n 500: 0.632,\n 600: 0.712,\n 700: 0.788,\n 800: 0.862,\n 900: 0.928,\n};\n\n/**\n * Chroma multiplier per step, relative to the input color's chroma.\n *\n * Peaks around `500`–`600` and falls off at both ends: near-white and near-black\n * tints hold very little chroma before they look muddy or leave the sRGB gamut.\n */\nconst CHROMA_CURVE: Record<ScaleStep, number> = {\n 50: 0.18,\n 100: 0.34,\n 200: 0.6,\n 300: 0.82,\n 400: 0.95,\n 500: 1,\n 600: 0.98,\n 700: 0.88,\n 800: 0.74,\n 900: 0.58,\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\n/** Expand `#abc` to `#aabbcc` and normalize to a lowercase 6-digit hex. */\nfunction normalizeHex(hex: string): string {\n const raw = hex.trim().replace(/^#/, \"\");\n const expanded =\n raw.length === 3 || raw.length === 4\n ? raw\n .slice(0, 3)\n .split(\"\")\n .map((char) => char + char)\n .join(\"\")\n : raw.slice(0, 6);\n if (!/^[0-9a-fA-F]{6}$/.test(expanded)) {\n throw new Error(`Invalid hex color: \"${hex}\"`);\n }\n return `#${expanded.toLowerCase()}`;\n}\n\n/** Parse a hex color into sRGB channels in the `0`–`1` range. */\nexport function hexToRgb(hex: string): { r: number; g: number; b: number } {\n const normalized = normalizeHex(hex).slice(1);\n return {\n r: parseInt(normalized.slice(0, 2), 16) / 255,\n g: parseInt(normalized.slice(2, 4), 16) / 255,\n b: parseInt(normalized.slice(4, 6), 16) / 255,\n };\n}\n\n/** Serialize sRGB channels (`0`–`1`, clamped) back to a `#rrggbb` string. */\nexport function rgbToHex(r: number, g: number, b: number): string {\n const channel = (value: number): string =>\n Math.round(clamp(value, 0, 1) * 255)\n .toString(16)\n .padStart(2, \"0\");\n return `#${channel(r)}${channel(g)}${channel(b)}`;\n}\n\nfunction srgbToLinear(channel: number): number {\n return channel <= 0.04045 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);\n}\n\nfunction linearToSrgb(channel: number): number {\n return channel <= 0.0031308 ? channel * 12.92 : 1.055 * Math.pow(channel, 1 / 2.4) - 0.055;\n}\n\n/** Convert a hex color to OKLCH. */\nexport function hexToOklch(hex: string): Oklch {\n const { r, g, b } = hexToRgb(hex);\n const lr = srgbToLinear(r);\n const lg = srgbToLinear(g);\n const lb = srgbToLinear(b);\n\n const long = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);\n const medium = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);\n const short = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);\n\n const l = 0.2104542553 * long + 0.793617785 * medium - 0.0040720468 * short;\n const a = 1.9779984951 * long - 2.428592205 * medium + 0.4505937099 * short;\n const bAxis = 0.0259040371 * long + 0.7827717662 * medium - 0.808675766 * short;\n\n const c = Math.sqrt(a * a + bAxis * bAxis);\n const hue = c < 1e-6 ? 0 : (Math.atan2(bAxis, a) * 180) / Math.PI;\n\n return { l, c, h: hue < 0 ? hue + 360 : hue };\n}\n\n/** Convert OKLCH to linear-light sRGB, without gamut clamping. */\nfunction oklchToLinearRgb({ l, c, h }: Oklch): { r: number; g: number; b: number } {\n const hRad = (h * Math.PI) / 180;\n const a = Math.cos(hRad) * c;\n const bAxis = Math.sin(hRad) * c;\n\n const long = (l + 0.3963377774 * a + 0.2158037573 * bAxis) ** 3;\n const medium = (l - 0.1055613458 * a - 0.0638541728 * bAxis) ** 3;\n const short = (l - 0.0894841775 * a - 1.291485548 * bAxis) ** 3;\n\n return {\n r: 4.0767416621 * long - 3.3077115913 * medium + 0.2309699292 * short,\n g: -1.2684380046 * long + 2.6097574011 * medium - 0.3413193965 * short,\n b: -0.0041960863 * long - 0.7034186147 * medium + 1.707614701 * short,\n };\n}\n\nfunction inGamut({ r, g, b }: { r: number; g: number; b: number }): boolean {\n const epsilon = 1e-4;\n return (\n r >= -epsilon &&\n r <= 1 + epsilon &&\n g >= -epsilon &&\n g <= 1 + epsilon &&\n b >= -epsilon &&\n b <= 1 + epsilon\n );\n}\n\n/**\n * Convert OKLCH to a hex color, reducing chroma until the result fits sRGB.\n *\n * Lightness and hue are preserved: desaturating is far less noticeable than\n * shifting either of them, and a naive channel clamp would do both.\n */\nexport function oklchToHex(color: Oklch): string {\n let chroma = Math.max(0, color.c);\n let rgb = oklchToLinearRgb({ ...color, c: chroma });\n\n for (let i = 0; i < 24 && !inGamut(rgb); i += 1) {\n chroma *= 0.9;\n rgb = oklchToLinearRgb({ ...color, c: chroma });\n }\n\n return rgbToHex(linearToSrgb(rgb.r), linearToSrgb(rgb.g), linearToSrgb(rgb.b));\n}\n\n/** Options for {@link createColorScale}. */\nexport interface ColorScaleOptions {\n /**\n * Pin step `500` to the input color's exact lightness. Default `true`.\n *\n * Right for a **brand** color: the hex a designer hands over is the one the\n * buttons must be. Wrong for a **neutral**: nobody checks that `gray-500` is\n * exactly the input, while everybody notices that a surface stopped being\n * near-white — anchoring rescales both halves around the input and compresses\n * exactly the range a neutral needs wide. With `false`, the ramp keeps the\n * tuned lightness curve and the input only contributes hue and chroma (a warm\n * or cool neutral, as asked).\n */\n anchor?: boolean;\n /**\n * Use the neutral lightness curve instead of the brand one. Default `false`.\n *\n * The neutral curve is wider at both ends, which is what keeps\n * `text-muted`-on-`surface-3` above AA. Implies the ramp is meant for\n * surfaces, borders and text rather than for an action color.\n */\n neutral?: boolean;\n}\n\n/**\n * Build a ten-step tint scale from a single color.\n *\n * The input color's hue is kept throughout and its chroma sets the intensity of\n * the whole ramp, so a muted brand color yields a muted scale instead of being\n * \"corrected\" into something the brand never approved.\n *\n * @param hex - Any hex color (`#abc` or `#aabbcc`), the intended `500` step.\n * @param mode - `\"light\"` for a light→dark ramp, `\"dark\"` for the inverted ramp\n * used under `[data-tempest-theme=\"dark\"]`.\n * @param options - See {@link ColorScaleOptions}.\n */\nexport function createColorScale(\n hex: string,\n mode: \"light\" | \"dark\" = \"light\",\n options: ColorScaleOptions = {},\n): ColorScale {\n const base = hexToOklch(hex);\n const targets = options.neutral\n ? mode === \"dark\"\n ? NEUTRAL_DARK_LIGHTNESS\n : NEUTRAL_LIGHT_LIGHTNESS\n : mode === \"dark\"\n ? DARK_LIGHTNESS\n : LIGHT_LIGHTNESS;\n const lightness =\n options.anchor === false ? targets : anchorLightnessAt500(targets, base.l, mode);\n const scale = {} as ColorScale;\n\n for (const step of SCALE_STEPS) {\n scale[step] = oklchToHex({\n l: lightness[step],\n c: base.c * CHROMA_CURVE[step],\n h: base.h,\n });\n }\n\n return scale;\n}\n\n/** Widest lightness band a generated ramp may span, so both ends stay usable. */\nconst LIGHTNESS_CEILING = 0.985;\nconst LIGHTNESS_FLOOR = 0.12;\n\n/**\n * Re-anchor a lightness ramp so step `500` lands on the brand color exactly.\n *\n * Without this, `500` is forced onto the ramp's own target lightness: a brand\n * `#7c3aed` came back as `#9161fe` — same hue, same chroma, *re-lightened*. It\n * looks fine in isolation and is wrong anyway, because the one color a designer\n * hands over is the one the buttons must actually be.\n *\n * Each half of the ramp is scaled independently around the anchor, so the shape\n * of the original curve survives and the ramp stays monotonic even for a very\n * light brand (yellow) or a very dark one (navy) — those simply get a shorter\n * run on the crowded side.\n *\n * @param targets - The default per-step lightness for this scheme.\n * @param anchor - Lightness of the brand color, used verbatim at step `500`.\n * @param mode - `\"dark\"` inverts which side of the ramp is the light one.\n */\nfunction anchorLightnessAt500(\n targets: Record<ScaleStep, number>,\n anchor: number,\n mode: \"light\" | \"dark\",\n): Record<ScaleStep, number> {\n const anchored = {} as Record<ScaleStep, number>;\n const base = targets[500];\n const lightEnd = mode === \"dark\" ? targets[900] : targets[50];\n const darkEnd = mode === \"dark\" ? targets[50] : targets[900];\n\n const top = Math.min(LIGHTNESS_CEILING, Math.max(lightEnd, anchor + 0.05));\n const bottom = Math.max(LIGHTNESS_FLOOR, Math.min(darkEnd, anchor - 0.05));\n\n for (const step of SCALE_STEPS) {\n const target = targets[step];\n if (target === base) {\n anchored[step] = anchor;\n } else if (target > base) {\n const ratio = (target - base) / (lightEnd - base);\n anchored[step] = anchor + ratio * (top - anchor);\n } else {\n const ratio = (base - target) / (base - darkEnd);\n anchored[step] = anchor - ratio * (anchor - bottom);\n }\n }\n\n return anchored;\n}\n\n/** WCAG 2.x relative luminance of a hex color. */\nexport function relativeLuminance(hex: string): number {\n const { r, g, b } = hexToRgb(hex);\n return 0.2126 * srgbToLinear(r) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);\n}\n\n/** WCAG 2.x contrast ratio between two hex colors, from `1` to `21`. */\nexport function contrastRatio(a: string, b: string): number {\n const la = relativeLuminance(a);\n const lb = relativeLuminance(b);\n const lighter = Math.max(la, lb);\n const darker = Math.min(la, lb);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\n/**\n * Pick the readable foreground for a background, by contrast ratio.\n *\n * Used for `--tempest-primary-foreground`: a generated brand color can land\n * anywhere on the lightness axis, and hardcoding white would silently produce\n * unreadable buttons for light brands (yellow, lime, cyan).\n */\nexport function readableForeground(\n background: string,\n light = \"#ffffff\",\n dark = \"#101828\",\n): string {\n return contrastRatio(background, light) >= contrastRatio(background, dark) ? light : dark;\n}\n\n/** Format a hex color as `rgb(r g b / alpha)`, for focus rings and overlays. */\nexport function hexToRgbaString(hex: string, alpha: number): string {\n const { r, g, b } = hexToRgb(hex);\n const channel = (value: number): number => Math.round(clamp(value, 0, 1) * 255);\n return `rgb(${channel(r)} ${channel(g)} ${channel(b)} / ${clamp(alpha, 0, 1)})`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"color.js","names":[],"sources":["../../src/theme/color.ts"],"sourcesContent":["/**\n * @tempest-limits file-lines — OKLCH ↔ sRGB with the gamut mapping in between: the\n * transfer function, the LMS matrices, the chroma search that finds the nearest in-\n * gamut colour and the contrast ratio used to check it. Matrices split across files\n * are matrices that get edited one half at a time.\n */\n/**\n * Color math behind {@link createTheme} — OKLab/OKLCH conversions, tint scale\n * generation and WCAG contrast picking.\n *\n * Everything here is pure and dependency-free: the SDK generates brand ramps at\n * runtime in the browser, so a color library would be a disproportionate cost\n * for ~150 lines of well-specified math. OKLCH is used instead of HSL because\n * HSL lightness is not perceptual — an HSL ramp of a yellow and of a blue at the\n * same `L` read as wildly different brightness, which is exactly what breaks a\n * generated palette.\n */\n\n/** A color in the OKLCH space: perceptual lightness, chroma and hue. */\nexport interface Oklch {\n /** Perceptual lightness, `0` (black) to `1` (white). */\n l: number;\n /** Chroma (colorfulness). `0` is gray; sRGB rarely exceeds `~0.37`. */\n c: number;\n /** Hue angle in degrees, `0`–`360`. */\n h: number;\n}\n\n/** The ten steps of a Tempest tint scale, lightest to darkest. */\nexport type ScaleStep = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;\n\n/** A generated tint scale, keyed by step. */\nexport type ColorScale = Record<ScaleStep, string>;\n\nconst SCALE_STEPS: ScaleStep[] = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];\n\n/**\n * Target lightness per step for a **brand** ramp in light mode.\n *\n * These are the measured OKLCH lightnesses of the hand-written `--tempest-primary-*`\n * scale in `colors.css`, so a generated brand ramp lands in the same visual range\n * as the built-in one instead of merely near it.\n */\nconst LIGHT_LIGHTNESS: Record<ScaleStep, number> = {\n 50: 0.966,\n 100: 0.923,\n 200: 0.844,\n 300: 0.743,\n 400: 0.642,\n 500: 0.563,\n 600: 0.48,\n 700: 0.391,\n 800: 0.325,\n 900: 0.251,\n};\n\n/**\n * Target lightness per step for a **neutral** ramp in light mode — measured from\n * the hand-written `--tempest-gray-*` scale.\n *\n * Deliberately **wider** than the brand curve at both ends (`0.982` → `0.210` vs\n * `0.966` → `0.251`): a neutral carries surfaces that must read as near-white and\n * text that must read as near-black, and the pair `text-muted` on `surface-3` has\n * to clear AA. Reusing the brand curve for neutrals is what dropped that pair to\n * 3.5:1 and made the browser axe sweep fail on every generated theme.\n */\nconst NEUTRAL_LIGHT_LIGHTNESS: Record<ScaleStep, number> = {\n 50: 0.982,\n 100: 0.963,\n 200: 0.927,\n 300: 0.872,\n 400: 0.71,\n 500: 0.544,\n 600: 0.442,\n 700: 0.369,\n 800: 0.278,\n 900: 0.21,\n};\n\n/**\n * Neutral ramp for dark mode, measured from the `[data-tempest-theme=\"dark\"]`\n * surface/text tokens: `50` is the page background and `900` is text-grade.\n */\nconst NEUTRAL_DARK_LIGHTNESS: Record<ScaleStep, number> = {\n 50: 0.159,\n 100: 0.205,\n 200: 0.254,\n 300: 0.314,\n 400: 0.381,\n 500: 0.5,\n 600: 0.571,\n 700: 0.762,\n 800: 0.86,\n 900: 0.964,\n};\n\n/**\n * Target lightness for a dark-theme ramp — the ramp is **inverted**: `50` is the\n * darkest tint (a surface) and `900` the lightest (text-grade), matching the\n * `[data-tempest-theme=\"dark\"]` block in `colors.css`.\n */\nconst DARK_LIGHTNESS: Record<ScaleStep, number> = {\n 50: 0.238,\n 100: 0.288,\n 200: 0.362,\n 300: 0.452,\n 400: 0.544,\n 500: 0.632,\n 600: 0.712,\n 700: 0.788,\n 800: 0.862,\n 900: 0.928,\n};\n\n/**\n * Chroma multiplier per step, relative to the input color's chroma.\n *\n * Peaks around `500`–`600` and falls off at both ends: near-white and near-black\n * tints hold very little chroma before they look muddy or leave the sRGB gamut.\n */\nconst CHROMA_CURVE: Record<ScaleStep, number> = {\n 50: 0.18,\n 100: 0.34,\n 200: 0.6,\n 300: 0.82,\n 400: 0.95,\n 500: 1,\n 600: 0.98,\n 700: 0.88,\n 800: 0.74,\n 900: 0.58,\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\n/** Expand `#abc` to `#aabbcc` and normalize to a lowercase 6-digit hex. */\nfunction normalizeHex(hex: string): string {\n const raw = hex.trim().replace(/^#/, \"\");\n const expanded =\n raw.length === 3 || raw.length === 4\n ? raw\n .slice(0, 3)\n .split(\"\")\n .map((char) => char + char)\n .join(\"\")\n : raw.slice(0, 6);\n if (!/^[0-9a-fA-F]{6}$/.test(expanded)) {\n throw new Error(`Invalid hex color: \"${hex}\"`);\n }\n return `#${expanded.toLowerCase()}`;\n}\n\n/** Parse a hex color into sRGB channels in the `0`–`1` range. */\nexport function hexToRgb(hex: string): { r: number; g: number; b: number } {\n const normalized = normalizeHex(hex).slice(1);\n return {\n r: parseInt(normalized.slice(0, 2), 16) / 255,\n g: parseInt(normalized.slice(2, 4), 16) / 255,\n b: parseInt(normalized.slice(4, 6), 16) / 255,\n };\n}\n\n/** Serialize sRGB channels (`0`–`1`, clamped) back to a `#rrggbb` string. */\nexport function rgbToHex(r: number, g: number, b: number): string {\n const channel = (value: number): string =>\n Math.round(clamp(value, 0, 1) * 255)\n .toString(16)\n .padStart(2, \"0\");\n return `#${channel(r)}${channel(g)}${channel(b)}`;\n}\n\nfunction srgbToLinear(channel: number): number {\n return channel <= 0.04045 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);\n}\n\nfunction linearToSrgb(channel: number): number {\n return channel <= 0.0031308 ? channel * 12.92 : 1.055 * Math.pow(channel, 1 / 2.4) - 0.055;\n}\n\n/** Convert a hex color to OKLCH. */\nexport function hexToOklch(hex: string): Oklch {\n const { r, g, b } = hexToRgb(hex);\n const lr = srgbToLinear(r);\n const lg = srgbToLinear(g);\n const lb = srgbToLinear(b);\n\n const long = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);\n const medium = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);\n const short = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);\n\n const l = 0.2104542553 * long + 0.793617785 * medium - 0.0040720468 * short;\n const a = 1.9779984951 * long - 2.428592205 * medium + 0.4505937099 * short;\n const bAxis = 0.0259040371 * long + 0.7827717662 * medium - 0.808675766 * short;\n\n const c = Math.sqrt(a * a + bAxis * bAxis);\n const hue = c < 1e-6 ? 0 : (Math.atan2(bAxis, a) * 180) / Math.PI;\n\n return { l, c, h: hue < 0 ? hue + 360 : hue };\n}\n\n/** Convert OKLCH to linear-light sRGB, without gamut clamping. */\nfunction oklchToLinearRgb({ l, c, h }: Oklch): { r: number; g: number; b: number } {\n const hRad = (h * Math.PI) / 180;\n const a = Math.cos(hRad) * c;\n const bAxis = Math.sin(hRad) * c;\n\n const long = (l + 0.3963377774 * a + 0.2158037573 * bAxis) ** 3;\n const medium = (l - 0.1055613458 * a - 0.0638541728 * bAxis) ** 3;\n const short = (l - 0.0894841775 * a - 1.291485548 * bAxis) ** 3;\n\n return {\n r: 4.0767416621 * long - 3.3077115913 * medium + 0.2309699292 * short,\n g: -1.2684380046 * long + 2.6097574011 * medium - 0.3413193965 * short,\n b: -0.0041960863 * long - 0.7034186147 * medium + 1.707614701 * short,\n };\n}\n\nfunction inGamut({ r, g, b }: { r: number; g: number; b: number }): boolean {\n const epsilon = 1e-4;\n return (\n r >= -epsilon &&\n r <= 1 + epsilon &&\n g >= -epsilon &&\n g <= 1 + epsilon &&\n b >= -epsilon &&\n b <= 1 + epsilon\n );\n}\n\n/**\n * Convert OKLCH to a hex color, reducing chroma until the result fits sRGB.\n *\n * Lightness and hue are preserved: desaturating is far less noticeable than\n * shifting either of them, and a naive channel clamp would do both.\n */\nexport function oklchToHex(color: Oklch): string {\n let chroma = Math.max(0, color.c);\n let rgb = oklchToLinearRgb({ ...color, c: chroma });\n\n for (let i = 0; i < 24 && !inGamut(rgb); i += 1) {\n chroma *= 0.9;\n rgb = oklchToLinearRgb({ ...color, c: chroma });\n }\n\n return rgbToHex(linearToSrgb(rgb.r), linearToSrgb(rgb.g), linearToSrgb(rgb.b));\n}\n\n/** Options for {@link createColorScale}. */\nexport interface ColorScaleOptions {\n /**\n * Pin step `500` to the input color's exact lightness. Default `true`.\n *\n * Right for a **brand** color: the hex a designer hands over is the one the\n * buttons must be. Wrong for a **neutral**: nobody checks that `gray-500` is\n * exactly the input, while everybody notices that a surface stopped being\n * near-white — anchoring rescales both halves around the input and compresses\n * exactly the range a neutral needs wide. With `false`, the ramp keeps the\n * tuned lightness curve and the input only contributes hue and chroma (a warm\n * or cool neutral, as asked).\n */\n anchor?: boolean;\n /**\n * Use the neutral lightness curve instead of the brand one. Default `false`.\n *\n * The neutral curve is wider at both ends, which is what keeps\n * `text-muted`-on-`surface-3` above AA. Implies the ramp is meant for\n * surfaces, borders and text rather than for an action color.\n */\n neutral?: boolean;\n}\n\n/**\n * Build a ten-step tint scale from a single color.\n *\n * The input color's hue is kept throughout and its chroma sets the intensity of\n * the whole ramp, so a muted brand color yields a muted scale instead of being\n * \"corrected\" into something the brand never approved.\n *\n * @param hex - Any hex color (`#abc` or `#aabbcc`), the intended `500` step.\n * @param mode - `\"light\"` for a light→dark ramp, `\"dark\"` for the inverted ramp\n * used under `[data-tempest-theme=\"dark\"]`.\n * @param options - See {@link ColorScaleOptions}.\n */\nexport function createColorScale(\n hex: string,\n mode: \"light\" | \"dark\" = \"light\",\n options: ColorScaleOptions = {},\n): ColorScale {\n const base = hexToOklch(hex);\n const targets = options.neutral\n ? mode === \"dark\"\n ? NEUTRAL_DARK_LIGHTNESS\n : NEUTRAL_LIGHT_LIGHTNESS\n : mode === \"dark\"\n ? DARK_LIGHTNESS\n : LIGHT_LIGHTNESS;\n const lightness =\n options.anchor === false ? targets : anchorLightnessAt500(targets, base.l, mode);\n const scale = {} as ColorScale;\n\n for (const step of SCALE_STEPS) {\n scale[step] = oklchToHex({\n l: lightness[step],\n c: base.c * CHROMA_CURVE[step],\n h: base.h,\n });\n }\n\n return scale;\n}\n\n/** Widest lightness band a generated ramp may span, so both ends stay usable. */\nconst LIGHTNESS_CEILING = 0.985;\nconst LIGHTNESS_FLOOR = 0.12;\n\n/**\n * Re-anchor a lightness ramp so step `500` lands on the brand color exactly.\n *\n * Without this, `500` is forced onto the ramp's own target lightness: a brand\n * `#7c3aed` came back as `#9161fe` — same hue, same chroma, *re-lightened*. It\n * looks fine in isolation and is wrong anyway, because the one color a designer\n * hands over is the one the buttons must actually be.\n *\n * Each half of the ramp is scaled independently around the anchor, so the shape\n * of the original curve survives and the ramp stays monotonic even for a very\n * light brand (yellow) or a very dark one (navy) — those simply get a shorter\n * run on the crowded side.\n *\n * @param targets - The default per-step lightness for this scheme.\n * @param anchor - Lightness of the brand color, used verbatim at step `500`.\n * @param mode - `\"dark\"` inverts which side of the ramp is the light one.\n */\nfunction anchorLightnessAt500(\n targets: Record<ScaleStep, number>,\n anchor: number,\n mode: \"light\" | \"dark\",\n): Record<ScaleStep, number> {\n const anchored = {} as Record<ScaleStep, number>;\n const base = targets[500];\n const lightEnd = mode === \"dark\" ? targets[900] : targets[50];\n const darkEnd = mode === \"dark\" ? targets[50] : targets[900];\n\n const top = Math.min(LIGHTNESS_CEILING, Math.max(lightEnd, anchor + 0.05));\n const bottom = Math.max(LIGHTNESS_FLOOR, Math.min(darkEnd, anchor - 0.05));\n\n for (const step of SCALE_STEPS) {\n const target = targets[step];\n if (target === base) {\n anchored[step] = anchor;\n } else if (target > base) {\n const ratio = (target - base) / (lightEnd - base);\n anchored[step] = anchor + ratio * (top - anchor);\n } else {\n const ratio = (base - target) / (base - darkEnd);\n anchored[step] = anchor - ratio * (anchor - bottom);\n }\n }\n\n return anchored;\n}\n\n/** WCAG 2.x relative luminance of a hex color. */\nexport function relativeLuminance(hex: string): number {\n const { r, g, b } = hexToRgb(hex);\n return 0.2126 * srgbToLinear(r) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);\n}\n\n/** WCAG 2.x contrast ratio between two hex colors, from `1` to `21`. */\nexport function contrastRatio(a: string, b: string): number {\n const la = relativeLuminance(a);\n const lb = relativeLuminance(b);\n const lighter = Math.max(la, lb);\n const darker = Math.min(la, lb);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\n/**\n * Pick the readable foreground for a background, by contrast ratio.\n *\n * Used for `--tempest-primary-foreground`: a generated brand color can land\n * anywhere on the lightness axis, and hardcoding white would silently produce\n * unreadable buttons for light brands (yellow, lime, cyan).\n */\nexport function readableForeground(\n background: string,\n light = \"#ffffff\",\n dark = \"#101828\",\n): string {\n return contrastRatio(background, light) >= contrastRatio(background, dark) ? light : dark;\n}\n\n/** Format a hex color as `rgb(r g b / alpha)`, for focus rings and overlays. */\nexport function hexToRgbaString(hex: string, alpha: number): string {\n const { r, g, b } = hexToRgb(hex);\n const channel = (value: number): number => Math.round(clamp(value, 0, 1) * 255);\n return `rgb(${channel(r)} ${channel(g)} ${channel(b)} / ${clamp(alpha, 0, 1)})`;\n}\n"],"mappings":"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"}
package/dist/utils/cn.cjs CHANGED
@@ -1,2 +1,2 @@
1
- function e(...t){let n=[];for(let r of t)if(!(r==null||r===!1||r===!0)){if(typeof r==`string`)r&&n.push(r);else if(typeof r==`number`||typeof r==`bigint`)n.push(String(r));else if(Array.isArray(r)){let t=e(...r);t&&n.push(t)}}return n.join(` `)}exports.cn=e;
1
+ function e(...t){let n=[];for(let r of t)if(r!=null&&r!==!1&&r!==!0){if(typeof r==`string`)r&&n.push(r);else if(typeof r==`number`||typeof r==`bigint`)n.push(String(r));else if(Array.isArray(r)){let t=e(...r);t&&n.push(t)}}return n.join(` `)}exports.cn=e;
2
2
  //# sourceMappingURL=cn.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"cn.cjs","names":[],"sources":["../../src/utils/cn.ts"],"sourcesContent":["type ClassValue = string | number | bigint | boolean | null | undefined | ClassValue[];\n\n/**\n * Tiny classnames helper. Accepts strings, falsy values and nested arrays.\n *\n * @param values - Class entries, conditionally truthy.\n * @returns A single space-joined class string.\n */\nexport function cn(...values: ClassValue[]): string {\n const out: string[] = [];\n for (const value of values) {\n if (value === null || value === undefined || value === false || value === true) {\n continue;\n }\n if (typeof value === \"string\") {\n if (value) out.push(value);\n } else if (typeof value === \"number\" || typeof value === \"bigint\") {\n out.push(String(value));\n } else if (Array.isArray(value)) {\n const nested = cn(...value);\n if (nested) out.push(nested);\n }\n }\n return out.join(\" \");\n}\n"],"mappings":"AAQA,SAAgB,EAAG,GAAG,EAA8B,CAChD,IAAM,EAAgB,CAAC,EACvB,IAAK,IAAM,KAAS,EACZ,QAAU,MAA+B,IAAU,IAAS,IAAU,IAG1E,IAAI,OAAO,GAAU,SACb,GAAO,EAAI,KAAK,CAAK,OACtB,GAAI,OAAO,GAAU,UAAY,OAAO,GAAU,SACrD,EAAI,KAAK,OAAO,CAAK,CAAC,OACnB,GAAI,MAAM,QAAQ,CAAK,EAAG,CAC7B,IAAM,EAAS,EAAG,GAAG,CAAK,EACtB,GAAQ,EAAI,KAAK,CAAM,CAC/B,EAEJ,OAAO,EAAI,KAAK,GAAG,CACvB"}
1
+ {"version":3,"file":"cn.cjs","names":[],"sources":["../../src/utils/cn.ts"],"sourcesContent":["type ClassValue = string | number | bigint | boolean | null | undefined | ClassValue[];\n\n/**\n * Tiny classnames helper. Accepts strings, falsy values and nested arrays.\n *\n * @param values - Class entries, conditionally truthy.\n * @returns A single space-joined class string.\n */\nexport function cn(...values: ClassValue[]): string {\n const out: string[] = [];\n for (const value of values) {\n if (value === null || value === undefined || value === false || value === true) {\n continue;\n }\n if (typeof value === \"string\") {\n if (value) out.push(value);\n } else if (typeof value === \"number\" || typeof value === \"bigint\") {\n out.push(String(value));\n } else if (Array.isArray(value)) {\n const nested = cn(...value);\n if (nested) out.push(nested);\n }\n }\n return out.join(\" \");\n}\n"],"mappings":"AAQA,SAAgB,EAAG,GAAG,EAA8B,CAChD,IAAM,EAAgB,CAAC,EACvB,IAAK,IAAM,KAAS,EACZ,MAAU,MAA+B,IAAU,IAAS,IAAU,GAG1E,IAAI,OAAO,GAAU,SACb,GAAO,EAAI,KAAK,CAAK,OACtB,GAAI,OAAO,GAAU,UAAY,OAAO,GAAU,SACrD,EAAI,KAAK,OAAO,CAAK,CAAC,OACnB,GAAI,MAAM,QAAQ,CAAK,EAAG,CAC7B,IAAM,EAAS,EAAG,GAAG,CAAK,EACtB,GAAQ,EAAI,KAAK,CAAM,CAC/B,EAEJ,OAAO,EAAI,KAAK,GAAG,CACvB"}
package/dist/utils/cn.js CHANGED
@@ -1,7 +1,7 @@
1
1
  //#region src/utils/cn.ts
2
2
  function e(...t) {
3
3
  let n = [];
4
- for (let r of t) if (!(r == null || r === !1 || r === !0)) {
4
+ for (let r of t) if (r != null && r !== !1 && r !== !0) {
5
5
  if (typeof r == "string") r && n.push(r);
6
6
  else if (typeof r == "number" || typeof r == "bigint") n.push(String(r));
7
7
  else if (Array.isArray(r)) {
@@ -1 +1 @@
1
- {"version":3,"file":"cn.js","names":[],"sources":["../../src/utils/cn.ts"],"sourcesContent":["type ClassValue = string | number | bigint | boolean | null | undefined | ClassValue[];\n\n/**\n * Tiny classnames helper. Accepts strings, falsy values and nested arrays.\n *\n * @param values - Class entries, conditionally truthy.\n * @returns A single space-joined class string.\n */\nexport function cn(...values: ClassValue[]): string {\n const out: string[] = [];\n for (const value of values) {\n if (value === null || value === undefined || value === false || value === true) {\n continue;\n }\n if (typeof value === \"string\") {\n if (value) out.push(value);\n } else if (typeof value === \"number\" || typeof value === \"bigint\") {\n out.push(String(value));\n } else if (Array.isArray(value)) {\n const nested = cn(...value);\n if (nested) out.push(nested);\n }\n }\n return out.join(\" \");\n}\n"],"mappings":";AAQA,SAAgB,EAAG,GAAG,GAA8B;CAChD,IAAM,IAAgB,CAAC;CACvB,KAAK,IAAM,KAAS,GACZ,WAAU,QAA+B,MAAU,MAAS,MAAU,KAG1E;MAAI,OAAO,KAAU,UACb,KAAO,EAAI,KAAK,CAAK;OACtB,IAAI,OAAO,KAAU,YAAY,OAAO,KAAU,UACrD,EAAI,KAAK,OAAO,CAAK,CAAC;OACnB,IAAI,MAAM,QAAQ,CAAK,GAAG;GAC7B,IAAM,IAAS,EAAG,GAAG,CAAK;GAC1B,AAAI,KAAQ,EAAI,KAAK,CAAM;EAC/B;;CAEJ,OAAO,EAAI,KAAK,GAAG;AACvB"}
1
+ {"version":3,"file":"cn.js","names":[],"sources":["../../src/utils/cn.ts"],"sourcesContent":["type ClassValue = string | number | bigint | boolean | null | undefined | ClassValue[];\n\n/**\n * Tiny classnames helper. Accepts strings, falsy values and nested arrays.\n *\n * @param values - Class entries, conditionally truthy.\n * @returns A single space-joined class string.\n */\nexport function cn(...values: ClassValue[]): string {\n const out: string[] = [];\n for (const value of values) {\n if (value === null || value === undefined || value === false || value === true) {\n continue;\n }\n if (typeof value === \"string\") {\n if (value) out.push(value);\n } else if (typeof value === \"number\" || typeof value === \"bigint\") {\n out.push(String(value));\n } else if (Array.isArray(value)) {\n const nested = cn(...value);\n if (nested) out.push(nested);\n }\n }\n return out.join(\" \");\n}\n"],"mappings":";AAQA,SAAgB,EAAG,GAAG,GAA8B;CAChD,IAAM,IAAgB,CAAC;CACvB,KAAK,IAAM,KAAS,GACZ,SAAU,QAA+B,MAAU,MAAS,MAAU,IAG1E;MAAI,OAAO,KAAU,UACb,AAAA,KAAO,EAAI,KAAK,CAAK;OACtB,IAAI,OAAO,KAAU,YAAY,OAAO,KAAU,UACrD,EAAI,KAAK,OAAO,CAAK,CAAC;OACnB,IAAI,MAAM,QAAQ,CAAK,GAAG;GAC7B,IAAM,IAAS,EAAG,GAAG,CAAK;GAC1B,AAAI,KAAQ,EAAI,KAAK,CAAM;EAC/B;;CAEJ,OAAO,EAAI,KAAK,GAAG;AACvB"}
@@ -1,2 +1,2 @@
1
- function e(e){if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function t(e,t){let n={};for(let r of t)Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function n(e,t){let n=new Set(t),r={};for(let t of Object.keys(e))n.has(t)||(r[t]=e[t]);return r}function r(t,n){if(!e(t)||!e(n))return n===void 0?t:n;let i={...t};for(let t of Object.keys(n)){let a=n[t],o=i[t];e(o)&&e(a)?i[t]=r(o,a):i[t]=a}return i}function i(t){return t==null?!0:typeof t==`string`||Array.isArray(t)?t.length===0:t instanceof Map||t instanceof Set?t.size===0:e(t)?Object.keys(t).length===0:!1}exports.deepMerge=r,exports.isEmpty=i,exports.omit=n,exports.pick=t;
1
+ function e(e){if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function t(e,t){let n={};for(let r of t)Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function n(e,t){let n=new Set(t),r={};for(let t of Object.keys(e))n.has(t)||(r[t]=e[t]);return r}function r(t,n){if(!e(t)||!e(n))return n===void 0?t:n;let i={...t};for(let t of Object.keys(n)){let a=n[t],o=i[t];i[t]=e(o)&&e(a)?r(o,a):a}return i}function i(t){return t==null?!0:typeof t==`string`||Array.isArray(t)?t.length===0:t instanceof Map||t instanceof Set?t.size===0:e(t)?Object.keys(t).length===0:!1}exports.deepMerge=r,exports.isEmpty=i,exports.omit=n,exports.pick=t;
2
2
  //# sourceMappingURL=objects.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"objects.cjs","names":[],"sources":["../../src/utils/objects.ts"],"sourcesContent":["/**\n * Determine whether a value is a plain object literal.\n *\n * Returns `false` for arrays, `null`, dates, maps, sets, and class instances.\n *\n * @internal\n */\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Create a new object containing only the given `keys` from `obj`.\n *\n * Missing keys are skipped. The input is never mutated.\n *\n * @example\n * pick({ id: 1, name: \"Ana\", age: 30 }, [\"id\", \"name\"]);\n * // { id: 1, name: \"Ana\" }\n */\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\n/**\n * Create a new object with the given `keys` removed from `obj`.\n *\n * The input is never mutated.\n *\n * @example\n * omit({ id: 1, name: \"Ana\", age: 30 }, [\"age\"]);\n * // { id: 1, name: \"Ana\" }\n */\nexport function omit<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {\n const exclude = new Set<PropertyKey>(keys);\n const result = {} as Record<PropertyKey, unknown>;\n for (const key of Object.keys(obj) as (keyof T)[]) {\n if (!exclude.has(key)) {\n result[key] = obj[key];\n }\n }\n return result as Omit<T, K>;\n}\n\n/**\n * Recursively merge `source` into `target`, returning a new object.\n *\n * - Plain objects are merged key by key, recursing into nested plain objects.\n * - Arrays and non-plain values (dates, class instances, primitives) replace\n * the target value entirely — they are not merged element by element.\n * - Neither `target` nor `source` is mutated.\n *\n * @example\n * deepMerge(\n * { a: 1, nested: { x: 1, y: 2 } },\n * { nested: { y: 20, z: 30 } },\n * );\n * // { a: 1, nested: { x: 1, y: 20, z: 30 } }\n *\n * @example\n * deepMerge({ tags: [\"a\", \"b\"] }, { tags: [\"c\"] });\n * // { tags: [\"c\"] } (arrays replaced, not merged)\n */\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n if (!isPlainRecord(target) || !isPlainRecord(source)) {\n return (source === undefined ? target : (source as unknown as T)) as T;\n }\n const result: Record<string, unknown> = { ...target };\n for (const key of Object.keys(source)) {\n const sourceValue = (source as Record<string, unknown>)[key];\n const targetValue = result[key];\n if (isPlainRecord(targetValue) && isPlainRecord(sourceValue)) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else {\n result[key] = sourceValue;\n }\n }\n return result as T;\n}\n\n/**\n * Check whether a value is considered \"empty\".\n *\n * Returns `true` for `null`, `undefined`, empty strings, empty arrays, empty\n * plain objects, and empty `Map`/`Set` instances. Returns `false` for numbers\n * (including `0` and `NaN`), booleans, and dates, which are never empty.\n *\n * @example\n * isEmpty(null); // true\n * isEmpty(\"\"); // true\n * isEmpty([]); // true\n * isEmpty({}); // true\n * isEmpty(new Map()); // true\n * isEmpty(0); // false\n * isEmpty(false); // false\n * isEmpty(new Date()); // false\n */\nexport function isEmpty(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (typeof value === \"string\") return value.length === 0;\n if (Array.isArray(value)) return value.length === 0;\n if (value instanceof Map || value instanceof Set) return value.size === 0;\n if (isPlainRecord(value)) return Object.keys(value).length === 0;\n return false;\n}\n"],"mappings":"AAOA,SAAS,EAAc,EAAkD,CACrE,GAAI,OAAO,GAAU,WAAY,EAAgB,MAAO,GACxD,IAAM,EAAQ,OAAO,eAAe,CAAK,EACzC,OAAO,IAAU,OAAO,WAAa,IAAU,IACnD,CAWA,SAAgB,EAA0C,EAAQ,EAAuB,CACrF,IAAM,EAAS,CAAC,EAChB,IAAK,IAAM,KAAO,EACV,OAAO,UAAU,eAAe,KAAK,EAAK,CAAG,IAC7C,EAAO,GAAO,EAAI,IAG1B,OAAO,CACX,CAWA,SAAgB,EAA0C,EAAQ,EAAuB,CACrF,IAAM,EAAU,IAAI,IAAiB,CAAI,EACnC,EAAS,CAAC,EAChB,IAAK,IAAM,KAAO,OAAO,KAAK,CAAG,EACxB,EAAQ,IAAI,CAAG,IAChB,EAAO,GAAO,EAAI,IAG1B,OAAO,CACX,CAqBA,SAAgB,EAAa,EAAW,EAAuB,CAC3D,GAAI,CAAC,EAAc,CAAM,GAAK,CAAC,EAAc,CAAM,EAC/C,OAAQ,IAAW,IAAA,GAAY,EAAU,EAE7C,IAAM,EAAkC,CAAE,GAAG,CAAO,EACpD,IAAK,IAAM,KAAO,OAAO,KAAK,CAAM,EAAG,CACnC,IAAM,EAAe,EAAmC,GAClD,EAAc,EAAO,GACvB,EAAc,CAAW,GAAK,EAAc,CAAW,EACvD,EAAO,GAAO,EAAU,EAAa,CAAW,EAEhD,EAAO,GAAO,CAEtB,CACA,OAAO,CACX,CAmBA,SAAgB,EAAQ,EAAyB,CAM7C,OALI,GAAU,KAAoC,GAC9C,OAAO,GAAU,UACjB,MAAM,QAAQ,CAAK,EAAU,EAAM,SAAW,EAC9C,aAAiB,KAAO,aAAiB,IAAY,EAAM,OAAS,EACpE,EAAc,CAAK,EAAU,OAAO,KAAK,CAAK,CAAC,CAAC,SAAW,EACxD,EACX"}
1
+ {"version":3,"file":"objects.cjs","names":[],"sources":["../../src/utils/objects.ts"],"sourcesContent":["/**\n * Determine whether a value is a plain object literal.\n *\n * Returns `false` for arrays, `null`, dates, maps, sets, and class instances.\n *\n * @internal\n */\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Create a new object containing only the given `keys` from `obj`.\n *\n * Missing keys are skipped. The input is never mutated.\n *\n * @example\n * pick({ id: 1, name: \"Ana\", age: 30 }, [\"id\", \"name\"]);\n * // { id: 1, name: \"Ana\" }\n */\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\n/**\n * Create a new object with the given `keys` removed from `obj`.\n *\n * The input is never mutated.\n *\n * @example\n * omit({ id: 1, name: \"Ana\", age: 30 }, [\"age\"]);\n * // { id: 1, name: \"Ana\" }\n */\nexport function omit<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {\n const exclude = new Set<PropertyKey>(keys);\n const result = {} as Record<PropertyKey, unknown>;\n for (const key of Object.keys(obj) as (keyof T)[]) {\n if (!exclude.has(key)) {\n result[key] = obj[key];\n }\n }\n return result as Omit<T, K>;\n}\n\n/**\n * Recursively merge `source` into `target`, returning a new object.\n *\n * - Plain objects are merged key by key, recursing into nested plain objects.\n * - Arrays and non-plain values (dates, class instances, primitives) replace\n * the target value entirely — they are not merged element by element.\n * - Neither `target` nor `source` is mutated.\n *\n * @example\n * deepMerge(\n * { a: 1, nested: { x: 1, y: 2 } },\n * { nested: { y: 20, z: 30 } },\n * );\n * // { a: 1, nested: { x: 1, y: 20, z: 30 } }\n *\n * @example\n * deepMerge({ tags: [\"a\", \"b\"] }, { tags: [\"c\"] });\n * // { tags: [\"c\"] } (arrays replaced, not merged)\n */\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n if (!isPlainRecord(target) || !isPlainRecord(source)) {\n return (source === undefined ? target : (source as unknown as T)) as T;\n }\n const result: Record<string, unknown> = { ...target };\n for (const key of Object.keys(source)) {\n const sourceValue = (source as Record<string, unknown>)[key];\n const targetValue = result[key];\n if (isPlainRecord(targetValue) && isPlainRecord(sourceValue)) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else {\n result[key] = sourceValue;\n }\n }\n return result as T;\n}\n\n/**\n * Check whether a value is considered \"empty\".\n *\n * Returns `true` for `null`, `undefined`, empty strings, empty arrays, empty\n * plain objects, and empty `Map`/`Set` instances. Returns `false` for numbers\n * (including `0` and `NaN`), booleans, and dates, which are never empty.\n *\n * @example\n * isEmpty(null); // true\n * isEmpty(\"\"); // true\n * isEmpty([]); // true\n * isEmpty({}); // true\n * isEmpty(new Map()); // true\n * isEmpty(0); // false\n * isEmpty(false); // false\n * isEmpty(new Date()); // false\n */\nexport function isEmpty(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (typeof value === \"string\") return value.length === 0;\n if (Array.isArray(value)) return value.length === 0;\n if (value instanceof Map || value instanceof Set) return value.size === 0;\n if (isPlainRecord(value)) return Object.keys(value).length === 0;\n return false;\n}\n"],"mappings":"AAOA,SAAS,EAAc,EAAkD,CACrE,GAAI,OAAO,GAAU,WAAY,EAAgB,MAAO,GACxD,IAAM,EAAQ,OAAO,eAAe,CAAK,EACzC,OAAO,IAAU,OAAO,WAAa,IAAU,IACnD,CAWA,SAAgB,EAA0C,EAAQ,EAAuB,CACrF,IAAM,EAAS,CAAC,EAChB,IAAK,IAAM,KAAO,EACV,OAAO,UAAU,eAAe,KAAK,EAAK,CAAG,IAC7C,EAAO,GAAO,EAAI,IAG1B,OAAO,CACX,CAWA,SAAgB,EAA0C,EAAQ,EAAuB,CACrF,IAAM,EAAU,IAAI,IAAiB,CAAI,EACnC,EAAS,CAAC,EAChB,IAAK,IAAM,KAAO,OAAO,KAAK,CAAG,EACxB,EAAQ,IAAI,CAAG,IAChB,EAAO,GAAO,EAAI,IAG1B,OAAO,CACX,CAqBA,SAAgB,EAAa,EAAW,EAAuB,CAC3D,GAAI,CAAC,EAAc,CAAM,GAAK,CAAC,EAAc,CAAM,EAC/C,OAAQ,IAAW,IAAA,GAAY,EAAU,EAE7C,IAAM,EAAkC,CAAE,GAAG,CAAO,EACpD,IAAK,IAAM,KAAO,OAAO,KAAK,CAAM,EAAG,CACnC,IAAM,EAAe,EAAmC,GAClD,EAAc,EAAO,GAC3B,AAGI,EAAO,GAHP,EAAc,CAAW,GAAK,EAAc,CAAW,EACzC,EAAU,EAAa,CAAW,EAElC,CAEtB,CACA,OAAO,CACX,CAmBA,SAAgB,EAAQ,EAAyB,CAM7C,OALI,GAAU,KAAoC,GAC9C,OAAO,GAAU,UACjB,MAAM,QAAQ,CAAK,EAAU,EAAM,SAAW,EAC9C,aAAiB,KAAO,aAAiB,IAAY,EAAM,OAAS,EACpE,EAAc,CAAK,EAAU,OAAO,KAAK,CAAK,CAAC,CAAC,SAAW,EACxD,EACX"}
@@ -19,7 +19,7 @@ function r(t, n) {
19
19
  let i = { ...t };
20
20
  for (let t of Object.keys(n)) {
21
21
  let a = n[t], o = i[t];
22
- e(o) && e(a) ? i[t] = r(o, a) : i[t] = a;
22
+ i[t] = e(o) && e(a) ? r(o, a) : a;
23
23
  }
24
24
  return i;
25
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"objects.js","names":[],"sources":["../../src/utils/objects.ts"],"sourcesContent":["/**\n * Determine whether a value is a plain object literal.\n *\n * Returns `false` for arrays, `null`, dates, maps, sets, and class instances.\n *\n * @internal\n */\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Create a new object containing only the given `keys` from `obj`.\n *\n * Missing keys are skipped. The input is never mutated.\n *\n * @example\n * pick({ id: 1, name: \"Ana\", age: 30 }, [\"id\", \"name\"]);\n * // { id: 1, name: \"Ana\" }\n */\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\n/**\n * Create a new object with the given `keys` removed from `obj`.\n *\n * The input is never mutated.\n *\n * @example\n * omit({ id: 1, name: \"Ana\", age: 30 }, [\"age\"]);\n * // { id: 1, name: \"Ana\" }\n */\nexport function omit<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {\n const exclude = new Set<PropertyKey>(keys);\n const result = {} as Record<PropertyKey, unknown>;\n for (const key of Object.keys(obj) as (keyof T)[]) {\n if (!exclude.has(key)) {\n result[key] = obj[key];\n }\n }\n return result as Omit<T, K>;\n}\n\n/**\n * Recursively merge `source` into `target`, returning a new object.\n *\n * - Plain objects are merged key by key, recursing into nested plain objects.\n * - Arrays and non-plain values (dates, class instances, primitives) replace\n * the target value entirely — they are not merged element by element.\n * - Neither `target` nor `source` is mutated.\n *\n * @example\n * deepMerge(\n * { a: 1, nested: { x: 1, y: 2 } },\n * { nested: { y: 20, z: 30 } },\n * );\n * // { a: 1, nested: { x: 1, y: 20, z: 30 } }\n *\n * @example\n * deepMerge({ tags: [\"a\", \"b\"] }, { tags: [\"c\"] });\n * // { tags: [\"c\"] } (arrays replaced, not merged)\n */\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n if (!isPlainRecord(target) || !isPlainRecord(source)) {\n return (source === undefined ? target : (source as unknown as T)) as T;\n }\n const result: Record<string, unknown> = { ...target };\n for (const key of Object.keys(source)) {\n const sourceValue = (source as Record<string, unknown>)[key];\n const targetValue = result[key];\n if (isPlainRecord(targetValue) && isPlainRecord(sourceValue)) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else {\n result[key] = sourceValue;\n }\n }\n return result as T;\n}\n\n/**\n * Check whether a value is considered \"empty\".\n *\n * Returns `true` for `null`, `undefined`, empty strings, empty arrays, empty\n * plain objects, and empty `Map`/`Set` instances. Returns `false` for numbers\n * (including `0` and `NaN`), booleans, and dates, which are never empty.\n *\n * @example\n * isEmpty(null); // true\n * isEmpty(\"\"); // true\n * isEmpty([]); // true\n * isEmpty({}); // true\n * isEmpty(new Map()); // true\n * isEmpty(0); // false\n * isEmpty(false); // false\n * isEmpty(new Date()); // false\n */\nexport function isEmpty(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (typeof value === \"string\") return value.length === 0;\n if (Array.isArray(value)) return value.length === 0;\n if (value instanceof Map || value instanceof Set) return value.size === 0;\n if (isPlainRecord(value)) return Object.keys(value).length === 0;\n return false;\n}\n"],"mappings":";AAOA,SAAS,EAAc,GAAkD;CACrE,IAAI,OAAO,KAAU,aAAY,GAAgB,OAAO;CACxD,IAAM,IAAQ,OAAO,eAAe,CAAK;CACzC,OAAO,MAAU,OAAO,aAAa,MAAU;AACnD;AAWA,SAAgB,EAA0C,GAAQ,GAAuB;CACrF,IAAM,IAAS,CAAC;CAChB,KAAK,IAAM,KAAO,GACd,AAAI,OAAO,UAAU,eAAe,KAAK,GAAK,CAAG,MAC7C,EAAO,KAAO,EAAI;CAG1B,OAAO;AACX;AAWA,SAAgB,EAA0C,GAAQ,GAAuB;CACrF,IAAM,IAAU,IAAI,IAAiB,CAAI,GACnC,IAAS,CAAC;CAChB,KAAK,IAAM,KAAO,OAAO,KAAK,CAAG,GAC7B,AAAK,EAAQ,IAAI,CAAG,MAChB,EAAO,KAAO,EAAI;CAG1B,OAAO;AACX;AAqBA,SAAgB,EAAa,GAAW,GAAuB;CAC3D,IAAI,CAAC,EAAc,CAAM,KAAK,CAAC,EAAc,CAAM,GAC/C,OAAQ,MAAW,KAAA,IAAY,IAAU;CAE7C,IAAM,IAAkC,EAAE,GAAG,EAAO;CACpD,KAAK,IAAM,KAAO,OAAO,KAAK,CAAM,GAAG;EACnC,IAAM,IAAe,EAAmC,IAClD,IAAc,EAAO;EAC3B,AAAI,EAAc,CAAW,KAAK,EAAc,CAAW,IACvD,EAAO,KAAO,EAAU,GAAa,CAAW,IAEhD,EAAO,KAAO;CAEtB;CACA,OAAO;AACX;AAmBA,SAAgB,EAAQ,GAAyB;CAM7C,OALI,KAAU,OAAoC,KAC9C,OAAO,KAAU,YACjB,MAAM,QAAQ,CAAK,IAAU,EAAM,WAAW,IAC9C,aAAiB,OAAO,aAAiB,MAAY,EAAM,SAAS,IACpE,EAAc,CAAK,IAAU,OAAO,KAAK,CAAK,CAAC,CAAC,WAAW,IACxD;AACX"}
1
+ {"version":3,"file":"objects.js","names":[],"sources":["../../src/utils/objects.ts"],"sourcesContent":["/**\n * Determine whether a value is a plain object literal.\n *\n * Returns `false` for arrays, `null`, dates, maps, sets, and class instances.\n *\n * @internal\n */\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Create a new object containing only the given `keys` from `obj`.\n *\n * Missing keys are skipped. The input is never mutated.\n *\n * @example\n * pick({ id: 1, name: \"Ana\", age: 30 }, [\"id\", \"name\"]);\n * // { id: 1, name: \"Ana\" }\n */\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\n/**\n * Create a new object with the given `keys` removed from `obj`.\n *\n * The input is never mutated.\n *\n * @example\n * omit({ id: 1, name: \"Ana\", age: 30 }, [\"age\"]);\n * // { id: 1, name: \"Ana\" }\n */\nexport function omit<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {\n const exclude = new Set<PropertyKey>(keys);\n const result = {} as Record<PropertyKey, unknown>;\n for (const key of Object.keys(obj) as (keyof T)[]) {\n if (!exclude.has(key)) {\n result[key] = obj[key];\n }\n }\n return result as Omit<T, K>;\n}\n\n/**\n * Recursively merge `source` into `target`, returning a new object.\n *\n * - Plain objects are merged key by key, recursing into nested plain objects.\n * - Arrays and non-plain values (dates, class instances, primitives) replace\n * the target value entirely — they are not merged element by element.\n * - Neither `target` nor `source` is mutated.\n *\n * @example\n * deepMerge(\n * { a: 1, nested: { x: 1, y: 2 } },\n * { nested: { y: 20, z: 30 } },\n * );\n * // { a: 1, nested: { x: 1, y: 20, z: 30 } }\n *\n * @example\n * deepMerge({ tags: [\"a\", \"b\"] }, { tags: [\"c\"] });\n * // { tags: [\"c\"] } (arrays replaced, not merged)\n */\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n if (!isPlainRecord(target) || !isPlainRecord(source)) {\n return (source === undefined ? target : (source as unknown as T)) as T;\n }\n const result: Record<string, unknown> = { ...target };\n for (const key of Object.keys(source)) {\n const sourceValue = (source as Record<string, unknown>)[key];\n const targetValue = result[key];\n if (isPlainRecord(targetValue) && isPlainRecord(sourceValue)) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else {\n result[key] = sourceValue;\n }\n }\n return result as T;\n}\n\n/**\n * Check whether a value is considered \"empty\".\n *\n * Returns `true` for `null`, `undefined`, empty strings, empty arrays, empty\n * plain objects, and empty `Map`/`Set` instances. Returns `false` for numbers\n * (including `0` and `NaN`), booleans, and dates, which are never empty.\n *\n * @example\n * isEmpty(null); // true\n * isEmpty(\"\"); // true\n * isEmpty([]); // true\n * isEmpty({}); // true\n * isEmpty(new Map()); // true\n * isEmpty(0); // false\n * isEmpty(false); // false\n * isEmpty(new Date()); // false\n */\nexport function isEmpty(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (typeof value === \"string\") return value.length === 0;\n if (Array.isArray(value)) return value.length === 0;\n if (value instanceof Map || value instanceof Set) return value.size === 0;\n if (isPlainRecord(value)) return Object.keys(value).length === 0;\n return false;\n}\n"],"mappings":";AAOA,SAAS,EAAc,GAAkD;CACrE,IAAI,OAAO,KAAU,aAAY,GAAgB,OAAO;CACxD,IAAM,IAAQ,OAAO,eAAe,CAAK;CACzC,OAAO,MAAU,OAAO,aAAa,MAAU;AACnD;AAWA,SAAgB,EAA0C,GAAQ,GAAuB;CACrF,IAAM,IAAS,CAAC;CAChB,KAAK,IAAM,KAAO,GACd,AAAI,OAAO,UAAU,eAAe,KAAK,GAAK,CAAG,MAC7C,EAAO,KAAO,EAAI;CAG1B,OAAO;AACX;AAWA,SAAgB,EAA0C,GAAQ,GAAuB;CACrF,IAAM,IAAU,IAAI,IAAiB,CAAI,GACnC,IAAS,CAAC;CAChB,KAAK,IAAM,KAAO,OAAO,KAAK,CAAG,GAC7B,AAAK,EAAQ,IAAI,CAAG,MAChB,EAAO,KAAO,EAAI;CAG1B,OAAO;AACX;AAqBA,SAAgB,EAAa,GAAW,GAAuB;CAC3D,IAAI,CAAC,EAAc,CAAM,KAAK,CAAC,EAAc,CAAM,GAC/C,OAAQ,MAAW,KAAA,IAAY,IAAU;CAE7C,IAAM,IAAkC,EAAE,GAAG,EAAO;CACpD,KAAK,IAAM,KAAO,OAAO,KAAK,CAAM,GAAG;EACnC,IAAM,IAAe,EAAmC,IAClD,IAAc,EAAO;EAC3B,AAGI,EAAO,KAHP,EAAc,CAAW,KAAK,EAAc,CAAW,IACzC,EAAU,GAAa,CAAW,IAElC;CAEtB;CACA,OAAO;AACX;AAmBA,SAAgB,EAAQ,GAAyB;CAM7C,OALI,KAAU,OAAoC,KAC9C,OAAO,KAAU,YACjB,MAAM,QAAQ,CAAK,IAAU,EAAM,WAAW,IAC9C,aAAiB,OAAO,aAAiB,MAAY,EAAM,SAAS,IACpE,EAAc,CAAK,IAAU,OAAO,KAAK,CAAK,CAAC,CAAC,WAAW,IACxD;AACX"}
@@ -1,2 +1,2 @@
1
- let e=require("fflate");function t(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&apos;`)}function n(e){let t=e+1,n=``;for(;t>0;){let e=(t-1)%26;n=String.fromCharCode(65+e)+n,t=Math.floor((t-1)/26)}return n}function r(e){return typeof e==`number`?{v:e,t:`n`}:e===null||e===``?{v:``,t:`s`}:{v:e,t:`s`}}function i(e,n){return e.t===`n`?`<c r="${n}" t="n"><v>${e.v}</v></c>`:e.v===``?`<c r="${n}" t="inlineStr"><is><t></t></is></c>`:`<c r="${n}" t="inlineStr"><is><t xml:space="preserve">${t(e.v)}</t></is></c>`}function a(e,t){return`<row r="${t}">${e.map((e,r)=>i(e,`${n(r)}${t}`)).join(``)}</row>`}function o(e,t){return`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><dimension ref="${`A1:${n(Math.max(t-1,0))}${e.length}`}"/><sheetData>${e.map((e,t)=>a(e,t+1)).join(``)}</sheetData></worksheet>`}var s=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/></Types>`,c=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>`,l=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets><sheet name="Sheet1" sheetId="1" r:id="rId1"/></sheets></workbook>`,u=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/></Relationships>`;function d(t,n){let i=t.map(e=>({v:e,t:`s`})),a=n.map(e=>e.map(r)),d=o([i,...a],Math.max(t.length,...a.map(e=>e.length),0)),f=new TextEncoder;return(0,e.zipSync)({"[Content_Types].xml":f.encode(s),"_rels/.rels":f.encode(c),"xl/workbook.xml":f.encode(l),"xl/_rels/workbook.xml.rels":f.encode(u),"xl/worksheets/sheet1.xml":f.encode(d)})}exports.writeXlsx=d;
1
+ let e=require("fflate");function t(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&apos;`)}function n(e){let t=e+1,n=``;for(;t>0;){let e=(t-1)%26;n=String.fromCharCode(65+e)+n,t=Math.floor((t-1)/26)}return n}function r(e){return typeof e==`number`?{v:e,t:`n`}:e===null||e===``?{v:``,t:`s`}:{v:e,t:`s`}}function i(e,n){return e.t===`n`?`<c r="${n}" t="n"><v>${e.v}</v></c>`:e.v===``?`<c r="${n}" t="inlineStr"><is><t></t></is></c>`:`<c r="${n}" t="inlineStr"><is><t xml:space="preserve">${t(e.v)}</t></is></c>`}function a(e,t){return`<row r="${t}">${e.map((e,r)=>i(e,`${n(r)}${t}`)).join(``)}</row>`}function o(e,t){return`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><dimension ref="${`A1:${n(Math.max(t-1,0))}${e.length}`}"/><sheetData>${e.map((e,t)=>a(e,t+1)).join(``)}</sheetData></worksheet>`}var s=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/></Types>`,c=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>`,l=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets><sheet name="Sheet1" sheetId="1" r:id="rId1"/></sheets></workbook>`,u=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/></Relationships>`;function d(t,n){let i=t.map(e=>({v:e,t:`s`})),a=n.map(e=>e.map(r)),d=o([i,...a],Math.max(t.length,...a.map(e=>e.length),0)),f=new TextEncoder,p={"[Content_Types].xml":f.encode(s),"_rels/.rels":f.encode(c),"xl/workbook.xml":f.encode(l),"xl/_rels/workbook.xml.rels":f.encode(u),"xl/worksheets/sheet1.xml":f.encode(d)};return(0,e.zipSync)(p)}exports.writeXlsx=d;
2
2
  //# sourceMappingURL=xlsx.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"xlsx.cjs","names":[],"sources":["../../src/utils/xlsx.ts"],"sourcesContent":["import { zipSync, type Zippable } from \"fflate\";\n\n/** A single spreadsheet cell — a number, a string, or an empty cell. */\ntype Cell = { v: string; t: \"s\" } | { v: number; t: \"n\" } | { v: \"\"; t: \"s\" };\n\nfunction escapeXml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nfunction colLetter(index0: number): string {\n let n = index0 + 1;\n let result = \"\";\n while (n > 0) {\n const rem = (n - 1) % 26;\n result = String.fromCharCode(65 + rem) + result;\n n = Math.floor((n - 1) / 26);\n }\n return result;\n}\n\nfunction toCell(value: string | number | null): Cell {\n if (typeof value === \"number\") return { v: value, t: \"n\" };\n if (value === null || value === \"\") return { v: \"\", t: \"s\" };\n return { v: value, t: \"s\" };\n}\n\nfunction cellXml(cell: Cell, ref: string): string {\n if (cell.t === \"n\") return `<c r=\"${ref}\" t=\"n\"><v>${cell.v}</v></c>`;\n if (cell.v === \"\") return `<c r=\"${ref}\" t=\"inlineStr\"><is><t></t></is></c>`;\n return `<c r=\"${ref}\" t=\"inlineStr\"><is><t xml:space=\"preserve\">${escapeXml(cell.v)}</t></is></c>`;\n}\n\nfunction rowXml(cells: readonly Cell[], rowIndex1: number): string {\n const inner = cells.map((c, i) => cellXml(c, `${colLetter(i)}${rowIndex1}`)).join(\"\");\n return `<row r=\"${rowIndex1}\">${inner}</row>`;\n}\n\nfunction buildSheetXml(rows: readonly (readonly Cell[])[], columnCount: number): string {\n const dimension = `A1:${colLetter(Math.max(columnCount - 1, 0))}${rows.length}`;\n const body = rows.map((row, i) => rowXml(row, i + 1)).join(\"\");\n return (\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">` +\n `<dimension ref=\"${dimension}\"/>` +\n `<sheetData>${body}</sheetData>` +\n `</worksheet>`\n );\n}\n\nconst CONTENT_TYPES_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">` +\n `<Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>` +\n `<Default Extension=\"xml\" ContentType=\"application/xml\"/>` +\n `<Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>` +\n `<Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>` +\n `</Types>`;\n\nconst ROOT_RELS_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">` +\n `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>` +\n `</Relationships>`;\n\nconst WORKBOOK_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"` +\n ` xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">` +\n `<sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>` +\n `</workbook>`;\n\nconst WORKBOOK_RELS_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">` +\n `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>` +\n `</Relationships>`;\n\n/**\n * Write a minimal single-sheet Office Open XML (`.xlsx`) workbook and return\n * its bytes. No extra dependency beyond `fflate` — the archive is assembled and\n * deflated in-process.\n *\n * The output is UTF-8 throughout, so accents round-trip in\n * Excel/LibreOffice/Google Sheets without the BOM-detection fragility that\n * plagues CSV exports. The XML stays compact: inline strings (no shared-string\n * table), no styles, no merged cells. Numeric cells use the native `\"n\"` type\n * so spreadsheets recognise them as numbers; `null` renders as an empty cell.\n *\n * @param headers - Column headers written as the first row.\n * @param rows - Data rows; each value is a string, a number, or `null` (empty).\n * @returns The `.xlsx` file contents as a `Uint8Array`.\n *\n * @example\n * const bytes = writeXlsx(\n * [\"Name\", \"Score\"],\n * [[\"Ada\", 99], [\"Alan\", null]],\n * );\n * const blob = new Blob([bytes], {\n * type: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n * });\n */\nexport function writeXlsx(\n headers: readonly string[],\n rows: readonly (readonly (string | number | null)[])[],\n): Uint8Array {\n const headerRow: Cell[] = headers.map((h) => ({ v: h, t: \"s\" }));\n const dataRows: Cell[][] = rows.map((row) => row.map(toCell));\n const allRows: Cell[][] = [headerRow, ...dataRows];\n const columnCount = Math.max(headers.length, ...dataRows.map((row) => row.length), 0);\n const sheetXml = buildSheetXml(allRows, columnCount);\n\n const encoder = new TextEncoder();\n const archive: Zippable = {\n \"[Content_Types].xml\": encoder.encode(CONTENT_TYPES_XML),\n \"_rels/.rels\": encoder.encode(ROOT_RELS_XML),\n \"xl/workbook.xml\": encoder.encode(WORKBOOK_XML),\n \"xl/_rels/workbook.xml.rels\": encoder.encode(WORKBOOK_RELS_XML),\n \"xl/worksheets/sheet1.xml\": encoder.encode(sheetXml),\n };\n return zipSync(archive);\n}\n"],"mappings":"wBAKA,SAAS,EAAU,EAAuB,CACtC,OAAO,EACF,QAAQ,KAAM,OAAO,CAAC,CACtB,QAAQ,KAAM,MAAM,CAAC,CACrB,QAAQ,KAAM,MAAM,CAAC,CACrB,QAAQ,KAAM,QAAQ,CAAC,CACvB,QAAQ,KAAM,QAAQ,CAC/B,CAEA,SAAS,EAAU,EAAwB,CACvC,IAAI,EAAI,EAAS,EACb,EAAS,GACb,KAAO,EAAI,GAAG,CACV,IAAM,GAAO,EAAI,GAAK,GACtB,EAAS,OAAO,aAAa,GAAK,CAAG,EAAI,EACzC,EAAI,KAAK,OAAO,EAAI,GAAK,EAAE,CAC/B,CACA,OAAO,CACX,CAEA,SAAS,EAAO,EAAqC,CAGjD,OAFI,OAAO,GAAU,SAAiB,CAAE,EAAG,EAAO,EAAG,GAAI,EACrD,IAAU,MAAQ,IAAU,GAAW,CAAE,EAAG,GAAI,EAAG,GAAI,EACpD,CAAE,EAAG,EAAO,EAAG,GAAI,CAC9B,CAEA,SAAS,EAAQ,EAAY,EAAqB,CAG9C,OAFI,EAAK,IAAM,IAAY,SAAS,EAAI,aAAa,EAAK,EAAE,UACxD,EAAK,IAAM,GAAW,SAAS,EAAI,sCAChC,SAAS,EAAI,8CAA8C,EAAU,EAAK,CAAC,EAAE,cACxF,CAEA,SAAS,EAAO,EAAwB,EAA2B,CAE/D,MAAO,WAAW,EAAU,IADd,EAAM,KAAK,EAAG,IAAM,EAAQ,EAAG,GAAG,EAAU,CAAC,IAAI,GAAW,CAAC,CAAC,CAAC,KAAK,EAClD,EAAM,OAC1C,CAEA,SAAS,EAAc,EAAoC,EAA6B,CAGpF,MACI,uJAEmB,MALC,EAAU,KAAK,IAAI,EAAc,EAAG,CAAC,CAAC,IAAI,EAAK,SAKtC,gBAJpB,EAAK,KAAK,EAAK,IAAM,EAAO,EAAK,EAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAKzC,EAAK,yBAG3B,CAEA,IAAM,EACF,gjBAQE,EACF,0SAKE,EACF,8RAME,EACF,2SA6BJ,SAAgB,EACZ,EACA,EACU,CACV,IAAM,EAAoB,EAAQ,IAAK,IAAO,CAAE,EAAG,EAAG,EAAG,GAAI,EAAE,EACzD,EAAqB,EAAK,IAAK,GAAQ,EAAI,IAAI,CAAM,CAAC,EAGtD,EAAW,EAAc,CAFJ,EAAW,GAAG,CAEV,EADX,KAAK,IAAI,EAAQ,OAAQ,GAAG,EAAS,IAAK,GAAQ,EAAI,MAAM,EAAG,CAC3C,CAAW,EAE7C,EAAU,IAAI,YAQpB,OAAA,EAAA,EAAA,QAAA,CAAe,CANX,sBAAuB,EAAQ,OAAO,CAAiB,EACvD,cAAe,EAAQ,OAAO,CAAa,EAC3C,kBAAmB,EAAQ,OAAO,CAAY,EAC9C,6BAA8B,EAAQ,OAAO,CAAiB,EAC9D,2BAA4B,EAAQ,OAAO,CAAQ,CAExC,CAAO,CAC1B"}
1
+ {"version":3,"file":"xlsx.cjs","names":[],"sources":["../../src/utils/xlsx.ts"],"sourcesContent":["import { zipSync, type Zippable } from \"fflate\";\n\n/** A single spreadsheet cell — a number, a string, or an empty cell. */\ntype Cell = { v: string; t: \"s\" } | { v: number; t: \"n\" } | { v: \"\"; t: \"s\" };\n\nfunction escapeXml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nfunction colLetter(index0: number): string {\n let n = index0 + 1;\n let result = \"\";\n while (n > 0) {\n const rem = (n - 1) % 26;\n result = String.fromCharCode(65 + rem) + result;\n n = Math.floor((n - 1) / 26);\n }\n return result;\n}\n\nfunction toCell(value: string | number | null): Cell {\n if (typeof value === \"number\") return { v: value, t: \"n\" };\n if (value === null || value === \"\") return { v: \"\", t: \"s\" };\n return { v: value, t: \"s\" };\n}\n\nfunction cellXml(cell: Cell, ref: string): string {\n if (cell.t === \"n\") return `<c r=\"${ref}\" t=\"n\"><v>${cell.v}</v></c>`;\n if (cell.v === \"\") return `<c r=\"${ref}\" t=\"inlineStr\"><is><t></t></is></c>`;\n return `<c r=\"${ref}\" t=\"inlineStr\"><is><t xml:space=\"preserve\">${escapeXml(cell.v)}</t></is></c>`;\n}\n\nfunction rowXml(cells: readonly Cell[], rowIndex1: number): string {\n const inner = cells.map((c, i) => cellXml(c, `${colLetter(i)}${rowIndex1}`)).join(\"\");\n return `<row r=\"${rowIndex1}\">${inner}</row>`;\n}\n\nfunction buildSheetXml(rows: readonly (readonly Cell[])[], columnCount: number): string {\n const dimension = `A1:${colLetter(Math.max(columnCount - 1, 0))}${rows.length}`;\n const body = rows.map((row, i) => rowXml(row, i + 1)).join(\"\");\n return (\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">` +\n `<dimension ref=\"${dimension}\"/>` +\n `<sheetData>${body}</sheetData>` +\n `</worksheet>`\n );\n}\n\nconst CONTENT_TYPES_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">` +\n `<Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>` +\n `<Default Extension=\"xml\" ContentType=\"application/xml\"/>` +\n `<Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>` +\n `<Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>` +\n `</Types>`;\n\nconst ROOT_RELS_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">` +\n `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>` +\n `</Relationships>`;\n\nconst WORKBOOK_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"` +\n ` xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">` +\n `<sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>` +\n `</workbook>`;\n\nconst WORKBOOK_RELS_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">` +\n `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>` +\n `</Relationships>`;\n\n/**\n * Write a minimal single-sheet Office Open XML (`.xlsx`) workbook and return\n * its bytes. No extra dependency beyond `fflate` — the archive is assembled and\n * deflated in-process.\n *\n * The output is UTF-8 throughout, so accents round-trip in\n * Excel/LibreOffice/Google Sheets without the BOM-detection fragility that\n * plagues CSV exports. The XML stays compact: inline strings (no shared-string\n * table), no styles, no merged cells. Numeric cells use the native `\"n\"` type\n * so spreadsheets recognise them as numbers; `null` renders as an empty cell.\n *\n * @param headers - Column headers written as the first row.\n * @param rows - Data rows; each value is a string, a number, or `null` (empty).\n * @returns The `.xlsx` file contents, backed by a plain `ArrayBuffer` so the\n * bytes go straight into `new Blob([...])` — the default `Uint8Array` is\n * `Uint8Array<ArrayBufferLike>`, which `BlobPart` rejects because it also\n * admits `SharedArrayBuffer`.\n *\n * @example\n * const bytes = writeXlsx(\n * [\"Name\", \"Score\"],\n * [[\"Ada\", 99], [\"Alan\", null]],\n * );\n * const blob = new Blob([bytes], {\n * type: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n * });\n */\nexport function writeXlsx(\n headers: readonly string[],\n rows: readonly (readonly (string | number | null)[])[],\n): Uint8Array<ArrayBuffer> {\n const headerRow: Cell[] = headers.map((h) => ({ v: h, t: \"s\" }));\n const dataRows: Cell[][] = rows.map((row) => row.map(toCell));\n const allRows: Cell[][] = [headerRow, ...dataRows];\n const columnCount = Math.max(headers.length, ...dataRows.map((row) => row.length), 0);\n const sheetXml = buildSheetXml(allRows, columnCount);\n\n const encoder = new TextEncoder();\n const archive: Zippable = {\n \"[Content_Types].xml\": encoder.encode(CONTENT_TYPES_XML),\n \"_rels/.rels\": encoder.encode(ROOT_RELS_XML),\n \"xl/workbook.xml\": encoder.encode(WORKBOOK_XML),\n \"xl/_rels/workbook.xml.rels\": encoder.encode(WORKBOOK_RELS_XML),\n \"xl/worksheets/sheet1.xml\": encoder.encode(sheetXml),\n };\n return zipSync(archive);\n}\n"],"mappings":"wBAKA,SAAS,EAAU,EAAuB,CACtC,OAAO,EACF,QAAQ,KAAM,OAAO,CAAC,CACtB,QAAQ,KAAM,MAAM,CAAC,CACrB,QAAQ,KAAM,MAAM,CAAC,CACrB,QAAQ,KAAM,QAAQ,CAAC,CACvB,QAAQ,KAAM,QAAQ,CAC/B,CAEA,SAAS,EAAU,EAAwB,CACvC,IAAI,EAAI,EAAS,EACb,EAAS,GACb,KAAO,EAAI,GAAG,CACV,IAAM,GAAO,EAAI,GAAK,GACtB,EAAS,OAAO,aAAa,GAAK,CAAG,EAAI,EACzC,EAAI,KAAK,OAAO,EAAI,GAAK,EAAE,CAC/B,CACA,OAAO,CACX,CAEA,SAAS,EAAO,EAAqC,CAGjD,OAFI,OAAO,GAAU,SAAiB,CAAE,EAAG,EAAO,EAAG,GAAI,EACrD,IAAU,MAAQ,IAAU,GAAW,CAAE,EAAG,GAAI,EAAG,GAAI,EACpD,CAAE,EAAG,EAAO,EAAG,GAAI,CAC9B,CAEA,SAAS,EAAQ,EAAY,EAAqB,CAG9C,OAFI,EAAK,IAAM,IAAY,SAAS,EAAI,aAAa,EAAK,EAAE,UACxD,EAAK,IAAM,GAAW,SAAS,EAAI,sCAChC,SAAS,EAAI,8CAA8C,EAAU,EAAK,CAAC,EAAE,cACxF,CAEA,SAAS,EAAO,EAAwB,EAA2B,CAE/D,MAAO,WAAW,EAAU,IADd,EAAM,KAAK,EAAG,IAAM,EAAQ,EAAG,GAAG,EAAU,CAAC,IAAI,GAAW,CAAC,CAAC,CAAC,KAAK,EAClD,EAAM,OAC1C,CAEA,SAAS,EAAc,EAAoC,EAA6B,CAGpF,MACI,uJAEmB,MALC,EAAU,KAAK,IAAI,EAAc,EAAG,CAAC,CAAC,IAAI,EAAK,SAKtC,gBAJpB,EAAK,KAAK,EAAK,IAAM,EAAO,EAAK,EAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAKzC,EAAK,yBAG3B,CAEA,IAAM,EACF,gjBAQE,EACF,0SAKE,EACF,8RAME,EACF,2SAgCJ,SAAgB,EACZ,EACA,EACuB,CACvB,IAAM,EAAoB,EAAQ,IAAK,IAAO,CAAE,EAAG,EAAG,EAAG,GAAI,EAAE,EACzD,EAAqB,EAAK,IAAK,GAAQ,EAAI,IAAI,CAAM,CAAC,EAGtD,EAAW,EAAc,CAFJ,EAAW,GAAG,CAEV,EADX,KAAK,IAAI,EAAQ,OAAQ,GAAG,EAAS,IAAK,GAAQ,EAAI,MAAM,EAAG,CAC3C,CAAW,EAE7C,EAAU,IAAI,YACd,EAAoB,CACtB,sBAAuB,EAAQ,OAAO,CAAiB,EACvD,cAAe,EAAQ,OAAO,CAAa,EAC3C,kBAAmB,EAAQ,OAAO,CAAY,EAC9C,6BAA8B,EAAQ,OAAO,CAAiB,EAC9D,2BAA4B,EAAQ,OAAO,CAAQ,CACvD,EACA,OAAA,EAAO,EAAA,QAAA,CAAQ,CAAO,CAC1B"}
@@ -37,14 +37,14 @@ function d(t, n) {
37
37
  let i = t.map((e) => ({
38
38
  v: e,
39
39
  t: "s"
40
- })), a = n.map((e) => e.map(r)), d = o([i, ...a], Math.max(t.length, ...a.map((e) => e.length), 0)), f = new TextEncoder();
41
- return e({
40
+ })), a = n.map((e) => e.map(r)), d = o([i, ...a], Math.max(t.length, ...a.map((e) => e.length), 0)), f = new TextEncoder(), p = {
42
41
  "[Content_Types].xml": f.encode(s),
43
42
  "_rels/.rels": f.encode(c),
44
43
  "xl/workbook.xml": f.encode(l),
45
44
  "xl/_rels/workbook.xml.rels": f.encode(u),
46
45
  "xl/worksheets/sheet1.xml": f.encode(d)
47
- });
46
+ };
47
+ return e(p);
48
48
  }
49
49
  //#endregion
50
50
  export { d as writeXlsx };
@@ -1 +1 @@
1
- {"version":3,"file":"xlsx.js","names":[],"sources":["../../src/utils/xlsx.ts"],"sourcesContent":["import { zipSync, type Zippable } from \"fflate\";\n\n/** A single spreadsheet cell — a number, a string, or an empty cell. */\ntype Cell = { v: string; t: \"s\" } | { v: number; t: \"n\" } | { v: \"\"; t: \"s\" };\n\nfunction escapeXml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nfunction colLetter(index0: number): string {\n let n = index0 + 1;\n let result = \"\";\n while (n > 0) {\n const rem = (n - 1) % 26;\n result = String.fromCharCode(65 + rem) + result;\n n = Math.floor((n - 1) / 26);\n }\n return result;\n}\n\nfunction toCell(value: string | number | null): Cell {\n if (typeof value === \"number\") return { v: value, t: \"n\" };\n if (value === null || value === \"\") return { v: \"\", t: \"s\" };\n return { v: value, t: \"s\" };\n}\n\nfunction cellXml(cell: Cell, ref: string): string {\n if (cell.t === \"n\") return `<c r=\"${ref}\" t=\"n\"><v>${cell.v}</v></c>`;\n if (cell.v === \"\") return `<c r=\"${ref}\" t=\"inlineStr\"><is><t></t></is></c>`;\n return `<c r=\"${ref}\" t=\"inlineStr\"><is><t xml:space=\"preserve\">${escapeXml(cell.v)}</t></is></c>`;\n}\n\nfunction rowXml(cells: readonly Cell[], rowIndex1: number): string {\n const inner = cells.map((c, i) => cellXml(c, `${colLetter(i)}${rowIndex1}`)).join(\"\");\n return `<row r=\"${rowIndex1}\">${inner}</row>`;\n}\n\nfunction buildSheetXml(rows: readonly (readonly Cell[])[], columnCount: number): string {\n const dimension = `A1:${colLetter(Math.max(columnCount - 1, 0))}${rows.length}`;\n const body = rows.map((row, i) => rowXml(row, i + 1)).join(\"\");\n return (\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">` +\n `<dimension ref=\"${dimension}\"/>` +\n `<sheetData>${body}</sheetData>` +\n `</worksheet>`\n );\n}\n\nconst CONTENT_TYPES_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">` +\n `<Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>` +\n `<Default Extension=\"xml\" ContentType=\"application/xml\"/>` +\n `<Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>` +\n `<Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>` +\n `</Types>`;\n\nconst ROOT_RELS_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">` +\n `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>` +\n `</Relationships>`;\n\nconst WORKBOOK_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"` +\n ` xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">` +\n `<sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>` +\n `</workbook>`;\n\nconst WORKBOOK_RELS_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">` +\n `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>` +\n `</Relationships>`;\n\n/**\n * Write a minimal single-sheet Office Open XML (`.xlsx`) workbook and return\n * its bytes. No extra dependency beyond `fflate` — the archive is assembled and\n * deflated in-process.\n *\n * The output is UTF-8 throughout, so accents round-trip in\n * Excel/LibreOffice/Google Sheets without the BOM-detection fragility that\n * plagues CSV exports. The XML stays compact: inline strings (no shared-string\n * table), no styles, no merged cells. Numeric cells use the native `\"n\"` type\n * so spreadsheets recognise them as numbers; `null` renders as an empty cell.\n *\n * @param headers - Column headers written as the first row.\n * @param rows - Data rows; each value is a string, a number, or `null` (empty).\n * @returns The `.xlsx` file contents as a `Uint8Array`.\n *\n * @example\n * const bytes = writeXlsx(\n * [\"Name\", \"Score\"],\n * [[\"Ada\", 99], [\"Alan\", null]],\n * );\n * const blob = new Blob([bytes], {\n * type: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n * });\n */\nexport function writeXlsx(\n headers: readonly string[],\n rows: readonly (readonly (string | number | null)[])[],\n): Uint8Array {\n const headerRow: Cell[] = headers.map((h) => ({ v: h, t: \"s\" }));\n const dataRows: Cell[][] = rows.map((row) => row.map(toCell));\n const allRows: Cell[][] = [headerRow, ...dataRows];\n const columnCount = Math.max(headers.length, ...dataRows.map((row) => row.length), 0);\n const sheetXml = buildSheetXml(allRows, columnCount);\n\n const encoder = new TextEncoder();\n const archive: Zippable = {\n \"[Content_Types].xml\": encoder.encode(CONTENT_TYPES_XML),\n \"_rels/.rels\": encoder.encode(ROOT_RELS_XML),\n \"xl/workbook.xml\": encoder.encode(WORKBOOK_XML),\n \"xl/_rels/workbook.xml.rels\": encoder.encode(WORKBOOK_RELS_XML),\n \"xl/worksheets/sheet1.xml\": encoder.encode(sheetXml),\n };\n return zipSync(archive);\n}\n"],"mappings":";;AAKA,SAAS,EAAU,GAAuB;CACtC,OAAO,EACF,QAAQ,MAAM,OAAO,CAAC,CACtB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,MAAM,QAAQ,CAAC,CACvB,QAAQ,MAAM,QAAQ;AAC/B;AAEA,SAAS,EAAU,GAAwB;CACvC,IAAI,IAAI,IAAS,GACb,IAAS;CACb,OAAO,IAAI,IAAG;EACV,IAAM,KAAO,IAAI,KAAK;EAEtB,AADA,IAAS,OAAO,aAAa,KAAK,CAAG,IAAI,GACzC,IAAI,KAAK,OAAO,IAAI,KAAK,EAAE;CAC/B;CACA,OAAO;AACX;AAEA,SAAS,EAAO,GAAqC;CAGjD,OAFI,OAAO,KAAU,WAAiB;EAAE,GAAG;EAAO,GAAG;CAAI,IACrD,MAAU,QAAQ,MAAU,KAAW;EAAE,GAAG;EAAI,GAAG;CAAI,IACpD;EAAE,GAAG;EAAO,GAAG;CAAI;AAC9B;AAEA,SAAS,EAAQ,GAAY,GAAqB;CAG9C,OAFI,EAAK,MAAM,MAAY,SAAS,EAAI,aAAa,EAAK,EAAE,YACxD,EAAK,MAAM,KAAW,SAAS,EAAI,wCAChC,SAAS,EAAI,8CAA8C,EAAU,EAAK,CAAC,EAAE;AACxF;AAEA,SAAS,EAAO,GAAwB,GAA2B;CAE/D,OAAO,WAAW,EAAU,IADd,EAAM,KAAK,GAAG,MAAM,EAAQ,GAAG,GAAG,EAAU,CAAC,IAAI,GAAW,CAAC,CAAC,CAAC,KAAK,EAClD,EAAM;AAC1C;AAEA,SAAS,EAAc,GAAoC,GAA6B;CAGpF,OACI,uJAEmB,MALC,EAAU,KAAK,IAAI,IAAc,GAAG,CAAC,CAAC,IAAI,EAAK,SAKtC,gBAJpB,EAAK,KAAK,GAAK,MAAM,EAAO,GAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAKzC,EAAK;AAG3B;AAEA,IAAM,IACF,ykBAQE,IACF,yTAKE,IACF,+SAME,IACF;AA6BJ,SAAgB,EACZ,GACA,GACU;CACV,IAAM,IAAoB,EAAQ,KAAK,OAAO;EAAE,GAAG;EAAG,GAAG;CAAI,EAAE,GACzD,IAAqB,EAAK,KAAK,MAAQ,EAAI,IAAI,CAAM,CAAC,GAGtD,IAAW,EAAc,CAFJ,GAAW,GAAG,CAEV,GADX,KAAK,IAAI,EAAQ,QAAQ,GAAG,EAAS,KAAK,MAAQ,EAAI,MAAM,GAAG,CAC3C,CAAW,GAE7C,IAAU,IAAI,YAAY;CAQhC,OAAO,EAAQ;EANX,uBAAuB,EAAQ,OAAO,CAAiB;EACvD,eAAe,EAAQ,OAAO,CAAa;EAC3C,mBAAmB,EAAQ,OAAO,CAAY;EAC9C,8BAA8B,EAAQ,OAAO,CAAiB;EAC9D,4BAA4B,EAAQ,OAAO,CAAQ;CAExC,CAAO;AAC1B"}
1
+ {"version":3,"file":"xlsx.js","names":[],"sources":["../../src/utils/xlsx.ts"],"sourcesContent":["import { zipSync, type Zippable } from \"fflate\";\n\n/** A single spreadsheet cell — a number, a string, or an empty cell. */\ntype Cell = { v: string; t: \"s\" } | { v: number; t: \"n\" } | { v: \"\"; t: \"s\" };\n\nfunction escapeXml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nfunction colLetter(index0: number): string {\n let n = index0 + 1;\n let result = \"\";\n while (n > 0) {\n const rem = (n - 1) % 26;\n result = String.fromCharCode(65 + rem) + result;\n n = Math.floor((n - 1) / 26);\n }\n return result;\n}\n\nfunction toCell(value: string | number | null): Cell {\n if (typeof value === \"number\") return { v: value, t: \"n\" };\n if (value === null || value === \"\") return { v: \"\", t: \"s\" };\n return { v: value, t: \"s\" };\n}\n\nfunction cellXml(cell: Cell, ref: string): string {\n if (cell.t === \"n\") return `<c r=\"${ref}\" t=\"n\"><v>${cell.v}</v></c>`;\n if (cell.v === \"\") return `<c r=\"${ref}\" t=\"inlineStr\"><is><t></t></is></c>`;\n return `<c r=\"${ref}\" t=\"inlineStr\"><is><t xml:space=\"preserve\">${escapeXml(cell.v)}</t></is></c>`;\n}\n\nfunction rowXml(cells: readonly Cell[], rowIndex1: number): string {\n const inner = cells.map((c, i) => cellXml(c, `${colLetter(i)}${rowIndex1}`)).join(\"\");\n return `<row r=\"${rowIndex1}\">${inner}</row>`;\n}\n\nfunction buildSheetXml(rows: readonly (readonly Cell[])[], columnCount: number): string {\n const dimension = `A1:${colLetter(Math.max(columnCount - 1, 0))}${rows.length}`;\n const body = rows.map((row, i) => rowXml(row, i + 1)).join(\"\");\n return (\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">` +\n `<dimension ref=\"${dimension}\"/>` +\n `<sheetData>${body}</sheetData>` +\n `</worksheet>`\n );\n}\n\nconst CONTENT_TYPES_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">` +\n `<Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>` +\n `<Default Extension=\"xml\" ContentType=\"application/xml\"/>` +\n `<Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>` +\n `<Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>` +\n `</Types>`;\n\nconst ROOT_RELS_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">` +\n `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>` +\n `</Relationships>`;\n\nconst WORKBOOK_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"` +\n ` xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">` +\n `<sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>` +\n `</workbook>`;\n\nconst WORKBOOK_RELS_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n `<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">` +\n `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>` +\n `</Relationships>`;\n\n/**\n * Write a minimal single-sheet Office Open XML (`.xlsx`) workbook and return\n * its bytes. No extra dependency beyond `fflate` — the archive is assembled and\n * deflated in-process.\n *\n * The output is UTF-8 throughout, so accents round-trip in\n * Excel/LibreOffice/Google Sheets without the BOM-detection fragility that\n * plagues CSV exports. The XML stays compact: inline strings (no shared-string\n * table), no styles, no merged cells. Numeric cells use the native `\"n\"` type\n * so spreadsheets recognise them as numbers; `null` renders as an empty cell.\n *\n * @param headers - Column headers written as the first row.\n * @param rows - Data rows; each value is a string, a number, or `null` (empty).\n * @returns The `.xlsx` file contents, backed by a plain `ArrayBuffer` so the\n * bytes go straight into `new Blob([...])` — the default `Uint8Array` is\n * `Uint8Array<ArrayBufferLike>`, which `BlobPart` rejects because it also\n * admits `SharedArrayBuffer`.\n *\n * @example\n * const bytes = writeXlsx(\n * [\"Name\", \"Score\"],\n * [[\"Ada\", 99], [\"Alan\", null]],\n * );\n * const blob = new Blob([bytes], {\n * type: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n * });\n */\nexport function writeXlsx(\n headers: readonly string[],\n rows: readonly (readonly (string | number | null)[])[],\n): Uint8Array<ArrayBuffer> {\n const headerRow: Cell[] = headers.map((h) => ({ v: h, t: \"s\" }));\n const dataRows: Cell[][] = rows.map((row) => row.map(toCell));\n const allRows: Cell[][] = [headerRow, ...dataRows];\n const columnCount = Math.max(headers.length, ...dataRows.map((row) => row.length), 0);\n const sheetXml = buildSheetXml(allRows, columnCount);\n\n const encoder = new TextEncoder();\n const archive: Zippable = {\n \"[Content_Types].xml\": encoder.encode(CONTENT_TYPES_XML),\n \"_rels/.rels\": encoder.encode(ROOT_RELS_XML),\n \"xl/workbook.xml\": encoder.encode(WORKBOOK_XML),\n \"xl/_rels/workbook.xml.rels\": encoder.encode(WORKBOOK_RELS_XML),\n \"xl/worksheets/sheet1.xml\": encoder.encode(sheetXml),\n };\n return zipSync(archive);\n}\n"],"mappings":";;AAKA,SAAS,EAAU,GAAuB;CACtC,OAAO,EACF,QAAQ,MAAM,OAAO,CAAC,CACtB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,MAAM,MAAM,CAAC,CACrB,QAAQ,MAAM,QAAQ,CAAC,CACvB,QAAQ,MAAM,QAAQ;AAC/B;AAEA,SAAS,EAAU,GAAwB;CACvC,IAAI,IAAI,IAAS,GACb,IAAS;CACb,OAAO,IAAI,IAAG;EACV,IAAM,KAAO,IAAI,KAAK;EAEtB,AADA,IAAS,OAAO,aAAa,KAAK,CAAG,IAAI,GACzC,IAAI,KAAK,OAAO,IAAI,KAAK,EAAE;CAC/B;CACA,OAAO;AACX;AAEA,SAAS,EAAO,GAAqC;CAGjD,OAFI,OAAO,KAAU,WAAiB;EAAE,GAAG;EAAO,GAAG;CAAI,IACrD,MAAU,QAAQ,MAAU,KAAW;EAAE,GAAG;EAAI,GAAG;CAAI,IACpD;EAAE,GAAG;EAAO,GAAG;CAAI;AAC9B;AAEA,SAAS,EAAQ,GAAY,GAAqB;CAG9C,OAFI,EAAK,MAAM,MAAY,SAAS,EAAI,aAAa,EAAK,EAAE,YACxD,EAAK,MAAM,KAAW,SAAS,EAAI,wCAChC,SAAS,EAAI,8CAA8C,EAAU,EAAK,CAAC,EAAE;AACxF;AAEA,SAAS,EAAO,GAAwB,GAA2B;CAE/D,OAAO,WAAW,EAAU,IADd,EAAM,KAAK,GAAG,MAAM,EAAQ,GAAG,GAAG,EAAU,CAAC,IAAI,GAAW,CAAC,CAAC,CAAC,KAAK,EAClD,EAAM;AAC1C;AAEA,SAAS,EAAc,GAAoC,GAA6B;CAGpF,OACI,uJAEmB,MALC,EAAU,KAAK,IAAI,IAAc,GAAG,CAAC,CAAC,IAAI,EAAK,SAKtC,gBAJpB,EAAK,KAAK,GAAK,MAAM,EAAO,GAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAKzC,EAAK;AAG3B;AAEA,IAAM,IACF,ykBAQE,IACF,yTAKE,IACF,+SAME,IACF;AAgCJ,SAAgB,EACZ,GACA,GACuB;CACvB,IAAM,IAAoB,EAAQ,KAAK,OAAO;EAAE,GAAG;EAAG,GAAG;CAAI,EAAE,GACzD,IAAqB,EAAK,KAAK,MAAQ,EAAI,IAAI,CAAM,CAAC,GAGtD,IAAW,EAAc,CAFJ,GAAW,GAAG,CAEV,GADX,KAAK,IAAI,EAAQ,QAAQ,GAAG,EAAS,KAAK,MAAQ,EAAI,MAAM,GAAG,CAC3C,CAAW,GAE7C,IAAU,IAAI,YAAY,GAC1B,IAAoB;EACtB,uBAAuB,EAAQ,OAAO,CAAiB;EACvD,eAAe,EAAQ,OAAO,CAAa;EAC3C,mBAAmB,EAAQ,OAAO,CAAY;EAC9C,8BAA8B,EAAQ,OAAO,CAAiB;EAC9D,4BAA4B,EAAQ,OAAO,CAAQ;CACvD;CACA,OAAO,EAAQ,CAAO;AAC1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"exceptions.cjs","names":[],"sources":["../../../src/vision/core/exceptions.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Exceptions raised by the SDK.\n *\n * All exceptions inherit from {@link OrtVisionError}, so callers can catch\n * the base class to handle any SDK-originated failure uniformly.\n */\n\nexport class OrtVisionError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/** Raised when an ONNX model cannot be loaded into an inference session. */\nexport class ModelLoadError extends OrtVisionError {}\n\n/** Raised when ONNX Runtime fails while executing a model. */\nexport class InferenceError extends OrtVisionError {}\n\n/** Raised when a requested execution provider is not available. */\nexport class ProviderNotAvailableError extends OrtVisionError {}\n\n/** Raised when an input image cannot be decoded into the canonical format. */\nexport class ImageLoadError extends OrtVisionError {}\n\n/** Raised when class labels cannot be resolved from the supplied spec. */\nexport class LabelMapError extends OrtVisionError {}\n\n/**\n * Raised when a detection task finds nothing and was asked to treat that as an error.\n *\n * Only raised when the caller opts in with `raiseOnEmpty: true`. The default\n * stays an empty result, because \"the model looked and found nothing\" is a\n * successful inference, not a failure — a photo of an empty field is a valid\n * photo. What the flag is for is the opposite situation: a pipeline step whose\n * *precondition* is that something is there, where an empty result means the\n * caller should stop rather than quietly carry on with zero rows.\n *\n * \"Nothing was detected\" and \"nothing was confident enough\" are the same\n * condition here, since the confidence threshold is what decides what counts as\n * a detection in the first place.\n */\nexport class NoDetectionsError extends OrtVisionError {}\n\n/**\n * Raised when a model cannot be driven as a fused detect→classify pipeline.\n *\n * In the browser this means the file carries no `ovs.*` metadata — it is a\n * plain detector or classifier rather than something `ort_vision_sdk.compose`\n * produced — or the graph is missing an output the pipeline contract requires.\n * Building a pipeline is a Python-side build step; the browser only runs one.\n */\nexport class FusionError extends OrtVisionError {}\n"],"mappings":"AAQA,IAAa,EAAb,cAAoC,KAAM,CACtC,YAAY,EAAiB,EAAwB,CACjD,MAAM,EAAS,CAAO,EACtB,KAAK,KAAO,IAAI,OAAO,IAC3B,CACJ,EAGa,EAAb,cAAoC,CAAe,CAAC,EAGvC,EAAb,cAAoC,CAAe,CAAC,EAGvC,EAAb,cAA+C,CAAe,CAAC,EAGlD,EAAb,cAAoC,CAAe,CAAC,EAGvC,EAAb,cAAmC,CAAe,CAAC,EAgBtC,EAAb,cAAuC,CAAe,CAAC,EAU1C,EAAb,cAAiC,CAAe,CAAC"}
1
+ {"version":3,"file":"exceptions.cjs","names":[],"sources":["../../../src/vision/core/exceptions.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Exceptions raised by the SDK.\n *\n * All exceptions inherit from {@link OrtVisionError}, so callers can catch\n * the base class to handle any SDK-originated failure uniformly.\n */\n\nexport class OrtVisionError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/** Raised when an ONNX model cannot be loaded into an inference session. */\nexport class ModelLoadError extends OrtVisionError {}\n\n/** Raised when ONNX Runtime fails while executing a model. */\nexport class InferenceError extends OrtVisionError {}\n\n/** Raised when a requested execution provider is not available. */\nexport class ProviderNotAvailableError extends OrtVisionError {}\n\n/** Raised when an input image cannot be decoded into the canonical format. */\nexport class ImageLoadError extends OrtVisionError {}\n\n/** Raised when class labels cannot be resolved from the supplied spec. */\nexport class LabelMapError extends OrtVisionError {}\n\n/**\n * Raised when a detection task finds nothing and was asked to treat that as an error.\n *\n * Only raised when the caller opts in with `raiseOnEmpty: true`. The default\n * stays an empty result, because \"the model looked and found nothing\" is a\n * successful inference, not a failure — a photo of an empty field is a valid\n * photo. What the flag is for is the opposite situation: a pipeline step whose\n * *precondition* is that something is there, where an empty result means the\n * caller should stop rather than quietly carry on with zero rows.\n *\n * \"Nothing was detected\" and \"nothing was confident enough\" are the same\n * condition here, since the confidence threshold is what decides what counts as\n * a detection in the first place.\n */\nexport class NoDetectionsError extends OrtVisionError {}\n\n/**\n * Raised when a model cannot be driven as a fused detect→classify pipeline.\n *\n * In the browser this means the file carries no `ovs.*` metadata — it is a\n * plain detector or classifier rather than something `ort_vision_sdk.compose`\n * produced — or the graph is missing an output the pipeline contract requires.\n * Building a pipeline is a Python-side build step; the browser only runs one.\n */\nexport class FusionError extends OrtVisionError {}\n"],"mappings":"AAQA,IAAa,EAAb,cAAoC,KAAM,CACtC,YAAY,EAAiB,EAAwB,CACjD,MAAM,EAAS,CAAO,EACtB,KAAK,KAAO,WAAW,IAC3B,CACJ,EAGa,EAAb,cAAoC,CAAe,CAAC,EAGvC,EAAb,cAAoC,CAAe,CAAC,EAGvC,EAAb,cAA+C,CAAe,CAAC,EAGlD,EAAb,cAAoC,CAAe,CAAC,EAGvC,EAAb,cAAmC,CAAe,CAAC,EAgBtC,EAAb,cAAuC,CAAe,CAAC,EAU1C,EAAb,cAAiC,CAAe,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"exceptions.js","names":[],"sources":["../../../src/vision/core/exceptions.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Exceptions raised by the SDK.\n *\n * All exceptions inherit from {@link OrtVisionError}, so callers can catch\n * the base class to handle any SDK-originated failure uniformly.\n */\n\nexport class OrtVisionError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/** Raised when an ONNX model cannot be loaded into an inference session. */\nexport class ModelLoadError extends OrtVisionError {}\n\n/** Raised when ONNX Runtime fails while executing a model. */\nexport class InferenceError extends OrtVisionError {}\n\n/** Raised when a requested execution provider is not available. */\nexport class ProviderNotAvailableError extends OrtVisionError {}\n\n/** Raised when an input image cannot be decoded into the canonical format. */\nexport class ImageLoadError extends OrtVisionError {}\n\n/** Raised when class labels cannot be resolved from the supplied spec. */\nexport class LabelMapError extends OrtVisionError {}\n\n/**\n * Raised when a detection task finds nothing and was asked to treat that as an error.\n *\n * Only raised when the caller opts in with `raiseOnEmpty: true`. The default\n * stays an empty result, because \"the model looked and found nothing\" is a\n * successful inference, not a failure — a photo of an empty field is a valid\n * photo. What the flag is for is the opposite situation: a pipeline step whose\n * *precondition* is that something is there, where an empty result means the\n * caller should stop rather than quietly carry on with zero rows.\n *\n * \"Nothing was detected\" and \"nothing was confident enough\" are the same\n * condition here, since the confidence threshold is what decides what counts as\n * a detection in the first place.\n */\nexport class NoDetectionsError extends OrtVisionError {}\n\n/**\n * Raised when a model cannot be driven as a fused detect→classify pipeline.\n *\n * In the browser this means the file carries no `ovs.*` metadata — it is a\n * plain detector or classifier rather than something `ort_vision_sdk.compose`\n * produced — or the graph is missing an output the pipeline contract requires.\n * Building a pipeline is a Python-side build step; the browser only runs one.\n */\nexport class FusionError extends OrtVisionError {}\n"],"mappings":";AAQA,IAAa,IAAb,cAAoC,MAAM;CACtC,YAAY,GAAiB,GAAwB;EAEjD,AADA,MAAM,GAAS,CAAO,GACtB,KAAK,OAAO,IAAI,OAAO;CAC3B;AACJ,GAGa,IAAb,cAAoC,EAAe,CAAC,GAGvC,IAAb,cAAoC,EAAe,CAAC,GAGvC,IAAb,cAA+C,EAAe,CAAC,GAGlD,IAAb,cAAoC,EAAe,CAAC,GAGvC,IAAb,cAAmC,EAAe,CAAC,GAgBtC,IAAb,cAAuC,EAAe,CAAC,GAU1C,IAAb,cAAiC,EAAe,CAAC"}
1
+ {"version":3,"file":"exceptions.js","names":[],"sources":["../../../src/vision/core/exceptions.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Exceptions raised by the SDK.\n *\n * All exceptions inherit from {@link OrtVisionError}, so callers can catch\n * the base class to handle any SDK-originated failure uniformly.\n */\n\nexport class OrtVisionError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/** Raised when an ONNX model cannot be loaded into an inference session. */\nexport class ModelLoadError extends OrtVisionError {}\n\n/** Raised when ONNX Runtime fails while executing a model. */\nexport class InferenceError extends OrtVisionError {}\n\n/** Raised when a requested execution provider is not available. */\nexport class ProviderNotAvailableError extends OrtVisionError {}\n\n/** Raised when an input image cannot be decoded into the canonical format. */\nexport class ImageLoadError extends OrtVisionError {}\n\n/** Raised when class labels cannot be resolved from the supplied spec. */\nexport class LabelMapError extends OrtVisionError {}\n\n/**\n * Raised when a detection task finds nothing and was asked to treat that as an error.\n *\n * Only raised when the caller opts in with `raiseOnEmpty: true`. The default\n * stays an empty result, because \"the model looked and found nothing\" is a\n * successful inference, not a failure — a photo of an empty field is a valid\n * photo. What the flag is for is the opposite situation: a pipeline step whose\n * *precondition* is that something is there, where an empty result means the\n * caller should stop rather than quietly carry on with zero rows.\n *\n * \"Nothing was detected\" and \"nothing was confident enough\" are the same\n * condition here, since the confidence threshold is what decides what counts as\n * a detection in the first place.\n */\nexport class NoDetectionsError extends OrtVisionError {}\n\n/**\n * Raised when a model cannot be driven as a fused detect→classify pipeline.\n *\n * In the browser this means the file carries no `ovs.*` metadata — it is a\n * plain detector or classifier rather than something `ort_vision_sdk.compose`\n * produced — or the graph is missing an output the pipeline contract requires.\n * Building a pipeline is a Python-side build step; the browser only runs one.\n */\nexport class FusionError extends OrtVisionError {}\n"],"mappings":";AAQA,IAAa,IAAb,cAAoC,MAAM;CACtC,YAAY,GAAiB,GAAwB;EAEjD,AADA,MAAM,GAAS,CAAO,GACtB,KAAK,OAAO,WAAW;CAC3B;AACJ,GAGa,IAAb,cAAoC,EAAe,CAAC,GAGvC,IAAb,cAAoC,EAAe,CAAC,GAGvC,IAAb,cAA+C,EAAe,CAAC,GAGlD,IAAb,cAAoC,EAAe,CAAC,GAGvC,IAAb,cAAmC,EAAe,CAAC,GAgBtC,IAAb,cAAuC,EAAe,CAAC,GAU1C,IAAb,cAAiC,EAAe,CAAC"}
@@ -1,3 +1,3 @@
1
- function e(e){let t=0,n=0;for(;e.pos<e.end;){let r=e.bytes[e.pos];if(e.pos+=1,t+=(r&127)*2**n,!(r&128))return t;if(n+=7,n>63)return null}return null}function t(t,n){switch(n){case 0:return e(t)!==null;case 1:return t.pos+=8,t.pos<=t.end;case 2:{let n=e(t);return n===null?!1:(t.pos+=n,t.pos<=t.end)}case 5:return t.pos+=4,t.pos<=t.end;default:return!1}}function n(t){let n=e(t);if(n===null||n>1048576)return null;let r=t.pos,i=r+n;return i>t.end?null:(t.pos=i,{start:r,end:i})}function r(r,i,a){let o={bytes:r,end:a,pos:i},s=new TextDecoder(`utf-8`,{fatal:!1}),c=null,l=null;for(;o.pos<a;){let i=e(o);if(i===null)return null;let a=i>>>3,u=i&7;if(u===2&&(a===1||a===2)){let e=n(o);if(e===null)return null;let t=s.decode(r.subarray(e.start,e.end));a===1?c=t:l=t;continue}if(!t(o,u))return null}return c===null||l===null?null:[c,l]}function i(i){let a=i instanceof Uint8Array?i:new Uint8Array(i),o={bytes:a,end:a.length,pos:0},s={};for(;o.pos<o.end;){let i=e(o);if(i===null)break;let c=i>>>3,l=i&7;if(c===14&&l===2){let e=n(o);if(e===null)break;let t=r(a,e.start,e.end);t&&(s[t[0]]=t[1]);continue}if(!t(o,l))break}return s}function a(e){return o(e?.names)}function o(e){let t=e?.trim();if(!t||!t.startsWith(`{`)||!t.endsWith(`}`))return null;let n=t.slice(1,-1).trim();if(!n)return null;let r=new Map,i=/(-?\d+)\s*:\s*(?:'((?:[^'\\]|\\.)*)'|"((?:[^"\\]|\\.)*)")/g,a=0;for(let e of n.matchAll(i)){let t=Number(e[1]),n=e[2]??e[3];if(!Number.isInteger(t)||n===void 0)return null;r.set(t,s(n)),a+=e[0].length}if(r.size===0||n.length-a>r.size*3)return null;let o=[];for(let e=0;e<r.size;e+=1){let t=r.get(e);if(t===void 0)return null;o.push(t)}return o}function s(e){return e.replace(/\\(.)/g,(e,t)=>t===`n`?`
1
+ function e(e){let t=0,n=0;for(;e.pos<e.end;){let r=e.bytes[e.pos];if(e.pos+=1,t+=(r&127)*2**n,!(r&128))return t;if(n+=7,n>63)return null}return null}function t(t,n){switch(n){case 0:return e(t)!==null;case 1:return t.pos+=8,t.pos<=t.end;case 2:{let n=e(t);return n!==null&&(t.pos+=n,t.pos<=t.end)}case 5:return t.pos+=4,t.pos<=t.end;default:return!1}}function n(t){let n=e(t);if(n===null||n>1048576)return null;let r=t.pos,i=r+n;return i>t.end?null:(t.pos=i,{start:r,end:i})}function r(r,i,a){let o={bytes:r,end:a,pos:i},s=new TextDecoder(`utf-8`,{fatal:!1}),c=null,l=null;for(;o.pos<a;){let i=e(o);if(i===null)return null;let a=i>>>3,u=i&7;if(u===2&&(a===1||a===2)){let e=n(o);if(e===null)return null;let t=s.decode(r.subarray(e.start,e.end));a===1?c=t:l=t;continue}if(!t(o,u))return null}return c===null||l===null?null:[c,l]}function i(i){let a=i instanceof Uint8Array?i:new Uint8Array(i),o={bytes:a,end:a.length,pos:0},s={};for(;o.pos<o.end;){let i=e(o);if(i===null)break;let c=i>>>3,l=i&7;if(c===14&&l===2){let e=n(o);if(e===null)break;let t=r(a,e.start,e.end);t&&(s[t[0]]=t[1]);continue}if(!t(o,l))break}return s}function a(e){return o(e?.names)}function o(e){let t=e?.trim();if(!t||!t.startsWith(`{`)||!t.endsWith(`}`))return null;let n=t.slice(1,-1).trim();if(!n)return null;let r=new Map,i=/(-?\d+)\s*:\s*(?:'((?:[^'\\]|\\.)*)'|"((?:[^"\\]|\\.)*)")/g,a=0;for(let e of n.matchAll(i)){let t=Number(e[1]),n=e[2]??e[3];if(!Number.isInteger(t)||n===void 0)return null;r.set(t,s(n)),a+=e[0].length}if(r.size===0||n.length-a>r.size*3)return null;let o=[];for(let e=0;e<r.size;e+=1){let t=r.get(e);if(t===void 0)return null;o.push(t)}return o}function s(e){return e.replace(/\\(.)/g,(e,t)=>t===`n`?`
2
2
  `:t===`r`?`\r`:t===`t`?` `:t)}exports.modelNames=a,exports.parseNames=o,exports.readModelMetadata=i;
3
3
  //# sourceMappingURL=metadata.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.cjs","names":[],"sources":["../../../src/vision/core/metadata.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Read the metadata an exporter baked into a `.onnx` file.\n *\n * `onnxruntime-web` exposes input/output metadata but **not** the model's\n * custom metadata map, which is where Ultralytics writes `names`, `task` and\n * `imgsz`. The Python SDK gets it for free from\n * `InferenceSession.get_modelmeta().custom_metadata_map`; in the browser the\n * only way to the same information is to read it out of the file, so this\n * module walks just enough of the ModelProto wire format to collect\n * `metadata_props`.\n *\n * It never throws and never allocates unbounded: a truncated, hostile or\n * simply unexpected file yields an empty map, and every caller treats that as\n * \"the model says nothing\", falling back to what it was given.\n */\n\n/** Field number of `metadata_props` in `ModelProto` (repeated StringStringEntryProto). */\nconst MODEL_METADATA_PROPS_FIELD = 14;\n\n/** Field numbers of `key` and `value` in `StringStringEntryProto`. */\nconst ENTRY_KEY_FIELD = 1;\nconst ENTRY_VALUE_FIELD = 2;\n\n/** Protobuf wire types this reader understands. */\nconst WIRE_VARINT = 0;\nconst WIRE_FIXED64 = 1;\nconst WIRE_LENGTH_DELIMITED = 2;\nconst WIRE_FIXED32 = 5;\n\n/**\n * Hard ceiling on a single length-delimited field, as a guard against a corrupt\n * length turning into a huge slice. Model metadata values are strings — a class\n * name map for thousands of classes still fits well inside this.\n */\nconst MAX_FIELD_BYTES = 1 << 20;\n\n/** A cursor over a byte range, tracking its own position. */\ninterface Cursor {\n readonly bytes: Uint8Array;\n readonly end: number;\n pos: number;\n}\n\n/**\n * Read a base-128 varint.\n *\n * @param cursor Cursor to advance.\n * @returns The value, or `null` when the varint is truncated or overlong\n * (beyond the 64-bit range protobuf allows).\n */\nfunction readVarint(cursor: Cursor): number | null {\n let result = 0;\n let shift = 0;\n while (cursor.pos < cursor.end) {\n const byte = cursor.bytes[cursor.pos]!;\n cursor.pos += 1;\n result += (byte & 0x7f) * 2 ** shift;\n if ((byte & 0x80) === 0) return result;\n shift += 7;\n if (shift > 63) return null;\n }\n return null;\n}\n\n/**\n * Skip a field whose contents are not needed.\n *\n * @param cursor Cursor to advance past the field's payload.\n * @param wireType Wire type read from the field's tag.\n * @returns `true` when the field was skipped, `false` when the stream is\n * unreadable from here (unknown wire type or truncated payload).\n */\nfunction skipField(cursor: Cursor, wireType: number): boolean {\n switch (wireType) {\n case WIRE_VARINT:\n return readVarint(cursor) !== null;\n case WIRE_FIXED64:\n cursor.pos += 8;\n return cursor.pos <= cursor.end;\n case WIRE_LENGTH_DELIMITED: {\n const length = readVarint(cursor);\n if (length === null) return false;\n cursor.pos += length;\n return cursor.pos <= cursor.end;\n }\n case WIRE_FIXED32:\n cursor.pos += 4;\n return cursor.pos <= cursor.end;\n default:\n return false;\n }\n}\n\n/**\n * Read a length-delimited payload as a byte range.\n *\n * @param cursor Cursor to advance past the payload.\n * @returns Start and end offsets of the payload, or `null` when the length is\n * truncated, overruns the buffer, or exceeds {@link MAX_FIELD_BYTES}.\n */\nfunction readLengthDelimited(cursor: Cursor): { start: number; end: number } | null {\n const length = readVarint(cursor);\n if (length === null || length > MAX_FIELD_BYTES) return null;\n const start = cursor.pos;\n const end = start + length;\n if (end > cursor.end) return null;\n cursor.pos = end;\n return { start, end };\n}\n\n/**\n * Decode one `StringStringEntryProto` into a key/value pair.\n *\n * @param bytes The model buffer.\n * @param start Offset the entry's payload starts at.\n * @param end Offset the entry's payload ends at.\n * @returns The pair, or `null` when either half is missing or undecodable.\n */\nfunction readEntry(\n bytes: Uint8Array,\n start: number,\n end: number,\n): readonly [string, string] | null {\n const cursor: Cursor = { bytes, end, pos: start };\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n let key: string | null = null;\n let value: string | null = null;\n\n while (cursor.pos < end) {\n const tag = readVarint(cursor);\n if (tag === null) return null;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (\n wireType === WIRE_LENGTH_DELIMITED &&\n (field === ENTRY_KEY_FIELD || field === ENTRY_VALUE_FIELD)\n ) {\n const range = readLengthDelimited(cursor);\n if (range === null) return null;\n const text = decoder.decode(bytes.subarray(range.start, range.end));\n if (field === ENTRY_KEY_FIELD) key = text;\n else value = text;\n continue;\n }\n if (!skipField(cursor, wireType)) return null;\n }\n\n if (key === null || value === null) return null;\n return [key, value];\n}\n\n/**\n * Collect a model's custom metadata map straight out of its bytes.\n *\n * @param model The `.onnx` file contents.\n * @returns Key/value metadata — `names`, `task`, `imgsz`, ... for an\n * Ultralytics export — or an empty object when the file carries none or\n * cannot be walked.\n */\nexport function readModelMetadata(\n model: Uint8Array | ArrayBufferLike,\n): Readonly<Record<string, string>> {\n const bytes = model instanceof Uint8Array ? model : new Uint8Array(model);\n const cursor: Cursor = { bytes, end: bytes.length, pos: 0 };\n const metadata: Record<string, string> = {};\n\n while (cursor.pos < cursor.end) {\n const tag = readVarint(cursor);\n if (tag === null) break;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (field === MODEL_METADATA_PROPS_FIELD && wireType === WIRE_LENGTH_DELIMITED) {\n const range = readLengthDelimited(cursor);\n if (range === null) break;\n const entry = readEntry(bytes, range.start, range.end);\n if (entry) metadata[entry[0]] = entry[1];\n continue;\n }\n if (!skipField(cursor, wireType)) break;\n }\n\n return metadata;\n}\n\n/**\n * Read the class names an export baked into the model metadata.\n *\n * Ultralytics writes `names` as the Python `repr` of a `dict[int, str]` — e.g.\n * `\"{0: 'deworm', 1: 'not_deworm'}\"`. The value is parsed structurally (never\n * evaluated), and anything unparseable, non-`dict`, or not keyed by contiguous\n * integers from zero is rejected whole rather than half-applied: a partial name\n * map would silently mislabel predictions.\n *\n * @param metadata A model's custom metadata map.\n * @returns Class names in class-id order, or `null` when the model carries no\n * usable `names` entry.\n */\nexport function modelNames(\n metadata: Readonly<Record<string, string>> | undefined,\n): readonly string[] | null {\n return parseNames(metadata?.names);\n}\n\n/**\n * Parse a `repr`-encoded `dict[int, str]` class map.\n *\n * Split out of {@link modelNames} because the same encoding is reused by a\n * fused pipeline, which carries one class map per stage and therefore cannot\n * store both under the single `names` key Ultralytics uses.\n *\n * @param encoded The encoded map — e.g. `\"{0: 'deworm', 1: 'not_deworm'}\"`.\n * @returns Class names in class-id order, or `null` when the value is missing,\n * unparseable, not a `dict`, or not keyed by contiguous integers from zero.\n */\nexport function parseNames(encoded: string | undefined): readonly string[] | null {\n const raw = encoded?.trim();\n if (!raw || !raw.startsWith(\"{\") || !raw.endsWith(\"}\")) return null;\n\n const body = raw.slice(1, -1).trim();\n if (!body) return null;\n\n const names = new Map<number, string>();\n const entryPattern = /(-?\\d+)\\s*:\\s*(?:'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\")/g;\n let consumed = 0;\n for (const match of body.matchAll(entryPattern)) {\n const id = Number(match[1]);\n const text = match[2] ?? match[3];\n if (!Number.isInteger(id) || text === undefined) return null;\n names.set(id, unescapeQuoted(text));\n consumed += match[0].length;\n }\n if (names.size === 0) return null;\n\n const separators = body.length - consumed;\n if (separators > names.size * 3) return null;\n\n const ordered: string[] = [];\n for (let id = 0; id < names.size; id += 1) {\n const name = names.get(id);\n if (name === undefined) return null;\n ordered.push(name);\n }\n return ordered;\n}\n\n/**\n * Resolve the backslash escapes Python's `repr` emits inside a quoted string.\n *\n * @param text The quoted string's contents, escapes intact.\n * @returns The same text with `\\\\`, `\\'`, `\\\"`, `\\n`, `\\r` and `\\t` resolved.\n */\nfunction unescapeQuoted(text: string): string {\n return text.replace(/\\\\(.)/g, (_, char: string) => {\n if (char === \"n\") return \"\\n\";\n if (char === \"r\") return \"\\r\";\n if (char === \"t\") return \"\\t\";\n return char;\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"metadata.cjs","names":[],"sources":["../../../src/vision/core/metadata.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Read the metadata an exporter baked into a `.onnx` file.\n *\n * `onnxruntime-web` exposes input/output metadata but **not** the model's\n * custom metadata map, which is where Ultralytics writes `names`, `task` and\n * `imgsz`. The Python SDK gets it for free from\n * `InferenceSession.get_modelmeta().custom_metadata_map`; in the browser the\n * only way to the same information is to read it out of the file, so this\n * module walks just enough of the ModelProto wire format to collect\n * `metadata_props`.\n *\n * It never throws and never allocates unbounded: a truncated, hostile or\n * simply unexpected file yields an empty map, and every caller treats that as\n * \"the model says nothing\", falling back to what it was given.\n */\n\n/** Field number of `metadata_props` in `ModelProto` (repeated StringStringEntryProto). */\nconst MODEL_METADATA_PROPS_FIELD = 14;\n\n/** Field numbers of `key` and `value` in `StringStringEntryProto`. */\nconst ENTRY_KEY_FIELD = 1;\nconst ENTRY_VALUE_FIELD = 2;\n\n/** Protobuf wire types this reader understands. */\nconst WIRE_VARINT = 0;\nconst WIRE_FIXED64 = 1;\nconst WIRE_LENGTH_DELIMITED = 2;\nconst WIRE_FIXED32 = 5;\n\n/**\n * Hard ceiling on a single length-delimited field, as a guard against a corrupt\n * length turning into a huge slice. Model metadata values are strings — a class\n * name map for thousands of classes still fits well inside this.\n */\nconst MAX_FIELD_BYTES = 1 << 20;\n\n/** A cursor over a byte range, tracking its own position. */\ninterface Cursor {\n readonly bytes: Uint8Array;\n readonly end: number;\n pos: number;\n}\n\n/**\n * Read a base-128 varint.\n *\n * @param cursor Cursor to advance.\n * @returns The value, or `null` when the varint is truncated or overlong\n * (beyond the 64-bit range protobuf allows).\n */\nfunction readVarint(cursor: Cursor): number | null {\n let result = 0;\n let shift = 0;\n while (cursor.pos < cursor.end) {\n const byte = cursor.bytes[cursor.pos]!;\n cursor.pos += 1;\n result += (byte & 0x7f) * 2 ** shift;\n if ((byte & 0x80) === 0) return result;\n shift += 7;\n if (shift > 63) return null;\n }\n return null;\n}\n\n/**\n * Skip a field whose contents are not needed.\n *\n * @param cursor Cursor to advance past the field's payload.\n * @param wireType Wire type read from the field's tag.\n * @returns `true` when the field was skipped, `false` when the stream is\n * unreadable from here (unknown wire type or truncated payload).\n */\nfunction skipField(cursor: Cursor, wireType: number): boolean {\n switch (wireType) {\n case WIRE_VARINT:\n return readVarint(cursor) !== null;\n case WIRE_FIXED64:\n cursor.pos += 8;\n return cursor.pos <= cursor.end;\n case WIRE_LENGTH_DELIMITED: {\n const length = readVarint(cursor);\n if (length === null) return false;\n cursor.pos += length;\n return cursor.pos <= cursor.end;\n }\n case WIRE_FIXED32:\n cursor.pos += 4;\n return cursor.pos <= cursor.end;\n default:\n return false;\n }\n}\n\n/**\n * Read a length-delimited payload as a byte range.\n *\n * @param cursor Cursor to advance past the payload.\n * @returns Start and end offsets of the payload, or `null` when the length is\n * truncated, overruns the buffer, or exceeds {@link MAX_FIELD_BYTES}.\n */\nfunction readLengthDelimited(cursor: Cursor): { start: number; end: number } | null {\n const length = readVarint(cursor);\n if (length === null || length > MAX_FIELD_BYTES) return null;\n const start = cursor.pos;\n const end = start + length;\n if (end > cursor.end) return null;\n cursor.pos = end;\n return { start, end };\n}\n\n/**\n * Decode one `StringStringEntryProto` into a key/value pair.\n *\n * @param bytes The model buffer.\n * @param start Offset the entry's payload starts at.\n * @param end Offset the entry's payload ends at.\n * @returns The pair, or `null` when either half is missing or undecodable.\n */\nfunction readEntry(\n bytes: Uint8Array,\n start: number,\n end: number,\n): readonly [string, string] | null {\n const cursor: Cursor = { bytes, end, pos: start };\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n let key: string | null = null;\n let value: string | null = null;\n\n while (cursor.pos < end) {\n const tag = readVarint(cursor);\n if (tag === null) return null;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (\n wireType === WIRE_LENGTH_DELIMITED &&\n (field === ENTRY_KEY_FIELD || field === ENTRY_VALUE_FIELD)\n ) {\n const range = readLengthDelimited(cursor);\n if (range === null) return null;\n const text = decoder.decode(bytes.subarray(range.start, range.end));\n if (field === ENTRY_KEY_FIELD) key = text;\n else value = text;\n continue;\n }\n if (!skipField(cursor, wireType)) return null;\n }\n\n if (key === null || value === null) return null;\n return [key, value];\n}\n\n/**\n * Collect a model's custom metadata map straight out of its bytes.\n *\n * @param model The `.onnx` file contents.\n * @returns Key/value metadata — `names`, `task`, `imgsz`, ... for an\n * Ultralytics export — or an empty object when the file carries none or\n * cannot be walked.\n */\nexport function readModelMetadata(\n model: Uint8Array | ArrayBufferLike,\n): Readonly<Record<string, string>> {\n const bytes = model instanceof Uint8Array ? model : new Uint8Array(model);\n const cursor: Cursor = { bytes, end: bytes.length, pos: 0 };\n const metadata: Record<string, string> = {};\n\n while (cursor.pos < cursor.end) {\n const tag = readVarint(cursor);\n if (tag === null) break;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (field === MODEL_METADATA_PROPS_FIELD && wireType === WIRE_LENGTH_DELIMITED) {\n const range = readLengthDelimited(cursor);\n if (range === null) break;\n const entry = readEntry(bytes, range.start, range.end);\n if (entry) metadata[entry[0]] = entry[1];\n continue;\n }\n if (!skipField(cursor, wireType)) break;\n }\n\n return metadata;\n}\n\n/**\n * Read the class names an export baked into the model metadata.\n *\n * Ultralytics writes `names` as the Python `repr` of a `dict[int, str]` — e.g.\n * `\"{0: 'deworm', 1: 'not_deworm'}\"`. The value is parsed structurally (never\n * evaluated), and anything unparseable, non-`dict`, or not keyed by contiguous\n * integers from zero is rejected whole rather than half-applied: a partial name\n * map would silently mislabel predictions.\n *\n * @param metadata A model's custom metadata map.\n * @returns Class names in class-id order, or `null` when the model carries no\n * usable `names` entry.\n */\nexport function modelNames(\n metadata: Readonly<Record<string, string>> | undefined,\n): readonly string[] | null {\n return parseNames(metadata?.names);\n}\n\n/**\n * Parse a `repr`-encoded `dict[int, str]` class map.\n *\n * Split out of {@link modelNames} because the same encoding is reused by a\n * fused pipeline, which carries one class map per stage and therefore cannot\n * store both under the single `names` key Ultralytics uses.\n *\n * @param encoded The encoded map — e.g. `\"{0: 'deworm', 1: 'not_deworm'}\"`.\n * @returns Class names in class-id order, or `null` when the value is missing,\n * unparseable, not a `dict`, or not keyed by contiguous integers from zero.\n */\nexport function parseNames(encoded: string | undefined): readonly string[] | null {\n const raw = encoded?.trim();\n if (!raw || !raw.startsWith(\"{\") || !raw.endsWith(\"}\")) return null;\n\n const body = raw.slice(1, -1).trim();\n if (!body) return null;\n\n const names = new Map<number, string>();\n const entryPattern = /(-?\\d+)\\s*:\\s*(?:'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\")/g;\n let consumed = 0;\n for (const match of body.matchAll(entryPattern)) {\n const id = Number(match[1]);\n const text = match[2] ?? match[3];\n if (!Number.isInteger(id) || text === undefined) return null;\n names.set(id, unescapeQuoted(text));\n consumed += match[0].length;\n }\n if (names.size === 0) return null;\n\n const separators = body.length - consumed;\n if (separators > names.size * 3) return null;\n\n const ordered: string[] = [];\n for (let id = 0; id < names.size; id += 1) {\n const name = names.get(id);\n if (name === undefined) return null;\n ordered.push(name);\n }\n return ordered;\n}\n\n/**\n * Resolve the backslash escapes Python's `repr` emits inside a quoted string.\n *\n * @param text The quoted string's contents, escapes intact.\n * @returns The same text with `\\\\`, `\\'`, `\\\"`, `\\n`, `\\r` and `\\t` resolved.\n */\nfunction unescapeQuoted(text: string): string {\n return text.replace(/\\\\(.)/g, (_, char: string) => {\n if (char === \"n\") return \"\\n\";\n if (char === \"r\") return \"\\r\";\n if (char === \"t\") return \"\\t\";\n return char;\n });\n}\n"],"mappings":"AAmDA,SAAS,EAAW,EAA+B,CAC/C,IAAI,EAAS,EACT,EAAQ,EACZ,KAAO,EAAO,IAAM,EAAO,KAAK,CAC5B,IAAM,EAAO,EAAO,MAAM,EAAO,KAGjC,GAFA,EAAO,KAAO,EACd,IAAW,EAAO,KAAQ,GAAK,EAC/B,EAAK,EAAO,KAAa,OAAO,EAEhC,GADA,GAAS,EACL,EAAQ,GAAI,OAAO,IAC3B,CACA,OAAO,IACX,CAUA,SAAS,EAAU,EAAgB,EAA2B,CAC1D,OAAQ,EAAR,CACI,IAAK,GACD,OAAO,EAAW,CAAM,IAAM,KAClC,IAAK,GAED,MADA,GAAO,KAAO,EACP,EAAO,KAAO,EAAO,IAChC,IAAK,GAAuB,CACxB,IAAM,EAAS,EAAW,CAAM,EAGhC,OAFI,IAAW,OACf,EAAO,KAAO,EACP,EAAO,KAAO,EAAO,IAChC,CACA,IAAK,GAED,MADA,GAAO,KAAO,EACP,EAAO,KAAO,EAAO,IAChC,QACI,MAAO,EACf,CACJ,CASA,SAAS,EAAoB,EAAuD,CAChF,IAAM,EAAS,EAAW,CAAM,EAChC,GAAI,IAAW,MAAQ,EAAS,QAAiB,OAAO,KACxD,IAAM,EAAQ,EAAO,IACf,EAAM,EAAQ,EAGpB,OAFI,EAAM,EAAO,IAAY,MAC7B,EAAO,IAAM,EACN,CAAE,QAAO,KAAI,EACxB,CAUA,SAAS,EACL,EACA,EACA,EACgC,CAChC,IAAM,EAAiB,CAAE,QAAO,MAAK,IAAK,CAAM,EAC1C,EAAU,IAAI,YAAY,QAAS,CAAE,MAAO,EAAM,CAAC,EACrD,EAAqB,KACrB,EAAuB,KAE3B,KAAO,EAAO,IAAM,GAAK,CACrB,IAAM,EAAM,EAAW,CAAM,EAC7B,GAAI,IAAQ,KAAM,OAAO,KACzB,IAAM,EAAQ,IAAQ,EAChB,EAAW,EAAM,EACvB,GACI,IAAa,IACZ,IAAU,GAAmB,IAAU,GAC1C,CACE,IAAM,EAAQ,EAAoB,CAAM,EACxC,GAAI,IAAU,KAAM,OAAO,KAC3B,IAAM,EAAO,EAAQ,OAAO,EAAM,SAAS,EAAM,MAAO,EAAM,GAAG,CAAC,EAC9D,IAAU,EAAiB,EAAM,EAChC,EAAQ,EACb,QACJ,CACA,GAAI,CAAC,EAAU,EAAQ,CAAQ,EAAG,OAAO,IAC7C,CAGA,OADI,IAAQ,MAAQ,IAAU,KAAa,KACpC,CAAC,EAAK,CAAK,CACtB,CAUA,SAAgB,EACZ,EACgC,CAChC,IAAM,EAAQ,aAAiB,WAAa,EAAQ,IAAI,WAAW,CAAK,EAClE,EAAiB,CAAE,QAAO,IAAK,EAAM,OAAQ,IAAK,CAAE,EACpD,EAAmC,CAAC,EAE1C,KAAO,EAAO,IAAM,EAAO,KAAK,CAC5B,IAAM,EAAM,EAAW,CAAM,EAC7B,GAAI,IAAQ,KAAM,MAClB,IAAM,EAAQ,IAAQ,EAChB,EAAW,EAAM,EACvB,GAAI,IAAU,IAA8B,IAAa,EAAuB,CAC5E,IAAM,EAAQ,EAAoB,CAAM,EACxC,GAAI,IAAU,KAAM,MACpB,IAAM,EAAQ,EAAU,EAAO,EAAM,MAAO,EAAM,GAAG,EACjD,IAAO,EAAS,EAAM,IAAM,EAAM,IACtC,QACJ,CACA,GAAI,CAAC,EAAU,EAAQ,CAAQ,EAAG,KACtC,CAEA,OAAO,CACX,CAeA,SAAgB,EACZ,EACwB,CACxB,OAAO,EAAW,GAAU,KAAK,CACrC,CAaA,SAAgB,EAAW,EAAuD,CAC9E,IAAM,EAAM,GAAS,KAAK,EAC1B,GAAI,CAAC,GAAO,CAAC,EAAI,WAAW,GAAG,GAAK,CAAC,EAAI,SAAS,GAAG,EAAG,OAAO,KAE/D,IAAM,EAAO,EAAI,MAAM,EAAG,EAAE,CAAC,CAAC,KAAK,EACnC,GAAI,CAAC,EAAM,OAAO,KAElB,IAAM,EAAQ,IAAI,IACZ,EAAe,6DACjB,EAAW,EACf,IAAK,IAAM,KAAS,EAAK,SAAS,CAAY,EAAG,CAC7C,IAAM,EAAK,OAAO,EAAM,EAAE,EACpB,EAAO,EAAM,IAAM,EAAM,GAC/B,GAAI,CAAC,OAAO,UAAU,CAAE,GAAK,IAAS,IAAA,GAAW,OAAO,KACxD,EAAM,IAAI,EAAI,EAAe,CAAI,CAAC,EAClC,GAAY,EAAM,EAAE,CAAC,MACzB,CAIA,GAHI,EAAM,OAAS,GAEA,EAAK,OAAS,EAChB,EAAM,KAAO,EAAG,OAAO,KAExC,IAAM,EAAoB,CAAC,EAC3B,IAAK,IAAI,EAAK,EAAG,EAAK,EAAM,KAAM,GAAM,EAAG,CACvC,IAAM,EAAO,EAAM,IAAI,CAAE,EACzB,GAAI,IAAS,IAAA,GAAW,OAAO,KAC/B,EAAQ,KAAK,CAAI,CACrB,CACA,OAAO,CACX,CAQA,SAAS,EAAe,EAAsB,CAC1C,OAAO,EAAK,QAAQ,UAAW,EAAG,IAC1B,IAAS,IAAY;EACrB,IAAS,IAAY,KACrB,IAAS,IAAY,IAClB,CACV,CACL"}
@@ -13,7 +13,7 @@ function t(t, n) {
13
13
  case 1: return t.pos += 8, t.pos <= t.end;
14
14
  case 2: {
15
15
  let n = e(t);
16
- return n === null ? !1 : (t.pos += n, t.pos <= t.end);
16
+ return n !== null && (t.pos += n, t.pos <= t.end);
17
17
  }
18
18
  case 5: return t.pos += 4, t.pos <= t.end;
19
19
  default: return !1;
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.js","names":[],"sources":["../../../src/vision/core/metadata.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Read the metadata an exporter baked into a `.onnx` file.\n *\n * `onnxruntime-web` exposes input/output metadata but **not** the model's\n * custom metadata map, which is where Ultralytics writes `names`, `task` and\n * `imgsz`. The Python SDK gets it for free from\n * `InferenceSession.get_modelmeta().custom_metadata_map`; in the browser the\n * only way to the same information is to read it out of the file, so this\n * module walks just enough of the ModelProto wire format to collect\n * `metadata_props`.\n *\n * It never throws and never allocates unbounded: a truncated, hostile or\n * simply unexpected file yields an empty map, and every caller treats that as\n * \"the model says nothing\", falling back to what it was given.\n */\n\n/** Field number of `metadata_props` in `ModelProto` (repeated StringStringEntryProto). */\nconst MODEL_METADATA_PROPS_FIELD = 14;\n\n/** Field numbers of `key` and `value` in `StringStringEntryProto`. */\nconst ENTRY_KEY_FIELD = 1;\nconst ENTRY_VALUE_FIELD = 2;\n\n/** Protobuf wire types this reader understands. */\nconst WIRE_VARINT = 0;\nconst WIRE_FIXED64 = 1;\nconst WIRE_LENGTH_DELIMITED = 2;\nconst WIRE_FIXED32 = 5;\n\n/**\n * Hard ceiling on a single length-delimited field, as a guard against a corrupt\n * length turning into a huge slice. Model metadata values are strings — a class\n * name map for thousands of classes still fits well inside this.\n */\nconst MAX_FIELD_BYTES = 1 << 20;\n\n/** A cursor over a byte range, tracking its own position. */\ninterface Cursor {\n readonly bytes: Uint8Array;\n readonly end: number;\n pos: number;\n}\n\n/**\n * Read a base-128 varint.\n *\n * @param cursor Cursor to advance.\n * @returns The value, or `null` when the varint is truncated or overlong\n * (beyond the 64-bit range protobuf allows).\n */\nfunction readVarint(cursor: Cursor): number | null {\n let result = 0;\n let shift = 0;\n while (cursor.pos < cursor.end) {\n const byte = cursor.bytes[cursor.pos]!;\n cursor.pos += 1;\n result += (byte & 0x7f) * 2 ** shift;\n if ((byte & 0x80) === 0) return result;\n shift += 7;\n if (shift > 63) return null;\n }\n return null;\n}\n\n/**\n * Skip a field whose contents are not needed.\n *\n * @param cursor Cursor to advance past the field's payload.\n * @param wireType Wire type read from the field's tag.\n * @returns `true` when the field was skipped, `false` when the stream is\n * unreadable from here (unknown wire type or truncated payload).\n */\nfunction skipField(cursor: Cursor, wireType: number): boolean {\n switch (wireType) {\n case WIRE_VARINT:\n return readVarint(cursor) !== null;\n case WIRE_FIXED64:\n cursor.pos += 8;\n return cursor.pos <= cursor.end;\n case WIRE_LENGTH_DELIMITED: {\n const length = readVarint(cursor);\n if (length === null) return false;\n cursor.pos += length;\n return cursor.pos <= cursor.end;\n }\n case WIRE_FIXED32:\n cursor.pos += 4;\n return cursor.pos <= cursor.end;\n default:\n return false;\n }\n}\n\n/**\n * Read a length-delimited payload as a byte range.\n *\n * @param cursor Cursor to advance past the payload.\n * @returns Start and end offsets of the payload, or `null` when the length is\n * truncated, overruns the buffer, or exceeds {@link MAX_FIELD_BYTES}.\n */\nfunction readLengthDelimited(cursor: Cursor): { start: number; end: number } | null {\n const length = readVarint(cursor);\n if (length === null || length > MAX_FIELD_BYTES) return null;\n const start = cursor.pos;\n const end = start + length;\n if (end > cursor.end) return null;\n cursor.pos = end;\n return { start, end };\n}\n\n/**\n * Decode one `StringStringEntryProto` into a key/value pair.\n *\n * @param bytes The model buffer.\n * @param start Offset the entry's payload starts at.\n * @param end Offset the entry's payload ends at.\n * @returns The pair, or `null` when either half is missing or undecodable.\n */\nfunction readEntry(\n bytes: Uint8Array,\n start: number,\n end: number,\n): readonly [string, string] | null {\n const cursor: Cursor = { bytes, end, pos: start };\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n let key: string | null = null;\n let value: string | null = null;\n\n while (cursor.pos < end) {\n const tag = readVarint(cursor);\n if (tag === null) return null;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (\n wireType === WIRE_LENGTH_DELIMITED &&\n (field === ENTRY_KEY_FIELD || field === ENTRY_VALUE_FIELD)\n ) {\n const range = readLengthDelimited(cursor);\n if (range === null) return null;\n const text = decoder.decode(bytes.subarray(range.start, range.end));\n if (field === ENTRY_KEY_FIELD) key = text;\n else value = text;\n continue;\n }\n if (!skipField(cursor, wireType)) return null;\n }\n\n if (key === null || value === null) return null;\n return [key, value];\n}\n\n/**\n * Collect a model's custom metadata map straight out of its bytes.\n *\n * @param model The `.onnx` file contents.\n * @returns Key/value metadata — `names`, `task`, `imgsz`, ... for an\n * Ultralytics export — or an empty object when the file carries none or\n * cannot be walked.\n */\nexport function readModelMetadata(\n model: Uint8Array | ArrayBufferLike,\n): Readonly<Record<string, string>> {\n const bytes = model instanceof Uint8Array ? model : new Uint8Array(model);\n const cursor: Cursor = { bytes, end: bytes.length, pos: 0 };\n const metadata: Record<string, string> = {};\n\n while (cursor.pos < cursor.end) {\n const tag = readVarint(cursor);\n if (tag === null) break;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (field === MODEL_METADATA_PROPS_FIELD && wireType === WIRE_LENGTH_DELIMITED) {\n const range = readLengthDelimited(cursor);\n if (range === null) break;\n const entry = readEntry(bytes, range.start, range.end);\n if (entry) metadata[entry[0]] = entry[1];\n continue;\n }\n if (!skipField(cursor, wireType)) break;\n }\n\n return metadata;\n}\n\n/**\n * Read the class names an export baked into the model metadata.\n *\n * Ultralytics writes `names` as the Python `repr` of a `dict[int, str]` — e.g.\n * `\"{0: 'deworm', 1: 'not_deworm'}\"`. The value is parsed structurally (never\n * evaluated), and anything unparseable, non-`dict`, or not keyed by contiguous\n * integers from zero is rejected whole rather than half-applied: a partial name\n * map would silently mislabel predictions.\n *\n * @param metadata A model's custom metadata map.\n * @returns Class names in class-id order, or `null` when the model carries no\n * usable `names` entry.\n */\nexport function modelNames(\n metadata: Readonly<Record<string, string>> | undefined,\n): readonly string[] | null {\n return parseNames(metadata?.names);\n}\n\n/**\n * Parse a `repr`-encoded `dict[int, str]` class map.\n *\n * Split out of {@link modelNames} because the same encoding is reused by a\n * fused pipeline, which carries one class map per stage and therefore cannot\n * store both under the single `names` key Ultralytics uses.\n *\n * @param encoded The encoded map — e.g. `\"{0: 'deworm', 1: 'not_deworm'}\"`.\n * @returns Class names in class-id order, or `null` when the value is missing,\n * unparseable, not a `dict`, or not keyed by contiguous integers from zero.\n */\nexport function parseNames(encoded: string | undefined): readonly string[] | null {\n const raw = encoded?.trim();\n if (!raw || !raw.startsWith(\"{\") || !raw.endsWith(\"}\")) return null;\n\n const body = raw.slice(1, -1).trim();\n if (!body) return null;\n\n const names = new Map<number, string>();\n const entryPattern = /(-?\\d+)\\s*:\\s*(?:'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\")/g;\n let consumed = 0;\n for (const match of body.matchAll(entryPattern)) {\n const id = Number(match[1]);\n const text = match[2] ?? match[3];\n if (!Number.isInteger(id) || text === undefined) return null;\n names.set(id, unescapeQuoted(text));\n consumed += match[0].length;\n }\n if (names.size === 0) return null;\n\n const separators = body.length - consumed;\n if (separators > names.size * 3) return null;\n\n const ordered: string[] = [];\n for (let id = 0; id < names.size; id += 1) {\n const name = names.get(id);\n if (name === undefined) return null;\n ordered.push(name);\n }\n return ordered;\n}\n\n/**\n * Resolve the backslash escapes Python's `repr` emits inside a quoted string.\n *\n * @param text The quoted string's contents, escapes intact.\n * @returns The same text with `\\\\`, `\\'`, `\\\"`, `\\n`, `\\r` and `\\t` resolved.\n */\nfunction unescapeQuoted(text: string): string {\n return text.replace(/\\\\(.)/g, (_, char: string) => {\n if (char === \"n\") return \"\\n\";\n if (char === \"r\") return \"\\r\";\n if (char === \"t\") return \"\\t\";\n return char;\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"metadata.js","names":[],"sources":["../../../src/vision/core/metadata.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Read the metadata an exporter baked into a `.onnx` file.\n *\n * `onnxruntime-web` exposes input/output metadata but **not** the model's\n * custom metadata map, which is where Ultralytics writes `names`, `task` and\n * `imgsz`. The Python SDK gets it for free from\n * `InferenceSession.get_modelmeta().custom_metadata_map`; in the browser the\n * only way to the same information is to read it out of the file, so this\n * module walks just enough of the ModelProto wire format to collect\n * `metadata_props`.\n *\n * It never throws and never allocates unbounded: a truncated, hostile or\n * simply unexpected file yields an empty map, and every caller treats that as\n * \"the model says nothing\", falling back to what it was given.\n */\n\n/** Field number of `metadata_props` in `ModelProto` (repeated StringStringEntryProto). */\nconst MODEL_METADATA_PROPS_FIELD = 14;\n\n/** Field numbers of `key` and `value` in `StringStringEntryProto`. */\nconst ENTRY_KEY_FIELD = 1;\nconst ENTRY_VALUE_FIELD = 2;\n\n/** Protobuf wire types this reader understands. */\nconst WIRE_VARINT = 0;\nconst WIRE_FIXED64 = 1;\nconst WIRE_LENGTH_DELIMITED = 2;\nconst WIRE_FIXED32 = 5;\n\n/**\n * Hard ceiling on a single length-delimited field, as a guard against a corrupt\n * length turning into a huge slice. Model metadata values are strings — a class\n * name map for thousands of classes still fits well inside this.\n */\nconst MAX_FIELD_BYTES = 1 << 20;\n\n/** A cursor over a byte range, tracking its own position. */\ninterface Cursor {\n readonly bytes: Uint8Array;\n readonly end: number;\n pos: number;\n}\n\n/**\n * Read a base-128 varint.\n *\n * @param cursor Cursor to advance.\n * @returns The value, or `null` when the varint is truncated or overlong\n * (beyond the 64-bit range protobuf allows).\n */\nfunction readVarint(cursor: Cursor): number | null {\n let result = 0;\n let shift = 0;\n while (cursor.pos < cursor.end) {\n const byte = cursor.bytes[cursor.pos]!;\n cursor.pos += 1;\n result += (byte & 0x7f) * 2 ** shift;\n if ((byte & 0x80) === 0) return result;\n shift += 7;\n if (shift > 63) return null;\n }\n return null;\n}\n\n/**\n * Skip a field whose contents are not needed.\n *\n * @param cursor Cursor to advance past the field's payload.\n * @param wireType Wire type read from the field's tag.\n * @returns `true` when the field was skipped, `false` when the stream is\n * unreadable from here (unknown wire type or truncated payload).\n */\nfunction skipField(cursor: Cursor, wireType: number): boolean {\n switch (wireType) {\n case WIRE_VARINT:\n return readVarint(cursor) !== null;\n case WIRE_FIXED64:\n cursor.pos += 8;\n return cursor.pos <= cursor.end;\n case WIRE_LENGTH_DELIMITED: {\n const length = readVarint(cursor);\n if (length === null) return false;\n cursor.pos += length;\n return cursor.pos <= cursor.end;\n }\n case WIRE_FIXED32:\n cursor.pos += 4;\n return cursor.pos <= cursor.end;\n default:\n return false;\n }\n}\n\n/**\n * Read a length-delimited payload as a byte range.\n *\n * @param cursor Cursor to advance past the payload.\n * @returns Start and end offsets of the payload, or `null` when the length is\n * truncated, overruns the buffer, or exceeds {@link MAX_FIELD_BYTES}.\n */\nfunction readLengthDelimited(cursor: Cursor): { start: number; end: number } | null {\n const length = readVarint(cursor);\n if (length === null || length > MAX_FIELD_BYTES) return null;\n const start = cursor.pos;\n const end = start + length;\n if (end > cursor.end) return null;\n cursor.pos = end;\n return { start, end };\n}\n\n/**\n * Decode one `StringStringEntryProto` into a key/value pair.\n *\n * @param bytes The model buffer.\n * @param start Offset the entry's payload starts at.\n * @param end Offset the entry's payload ends at.\n * @returns The pair, or `null` when either half is missing or undecodable.\n */\nfunction readEntry(\n bytes: Uint8Array,\n start: number,\n end: number,\n): readonly [string, string] | null {\n const cursor: Cursor = { bytes, end, pos: start };\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n let key: string | null = null;\n let value: string | null = null;\n\n while (cursor.pos < end) {\n const tag = readVarint(cursor);\n if (tag === null) return null;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (\n wireType === WIRE_LENGTH_DELIMITED &&\n (field === ENTRY_KEY_FIELD || field === ENTRY_VALUE_FIELD)\n ) {\n const range = readLengthDelimited(cursor);\n if (range === null) return null;\n const text = decoder.decode(bytes.subarray(range.start, range.end));\n if (field === ENTRY_KEY_FIELD) key = text;\n else value = text;\n continue;\n }\n if (!skipField(cursor, wireType)) return null;\n }\n\n if (key === null || value === null) return null;\n return [key, value];\n}\n\n/**\n * Collect a model's custom metadata map straight out of its bytes.\n *\n * @param model The `.onnx` file contents.\n * @returns Key/value metadata — `names`, `task`, `imgsz`, ... for an\n * Ultralytics export — or an empty object when the file carries none or\n * cannot be walked.\n */\nexport function readModelMetadata(\n model: Uint8Array | ArrayBufferLike,\n): Readonly<Record<string, string>> {\n const bytes = model instanceof Uint8Array ? model : new Uint8Array(model);\n const cursor: Cursor = { bytes, end: bytes.length, pos: 0 };\n const metadata: Record<string, string> = {};\n\n while (cursor.pos < cursor.end) {\n const tag = readVarint(cursor);\n if (tag === null) break;\n const field = tag >>> 3;\n const wireType = tag & 0x07;\n if (field === MODEL_METADATA_PROPS_FIELD && wireType === WIRE_LENGTH_DELIMITED) {\n const range = readLengthDelimited(cursor);\n if (range === null) break;\n const entry = readEntry(bytes, range.start, range.end);\n if (entry) metadata[entry[0]] = entry[1];\n continue;\n }\n if (!skipField(cursor, wireType)) break;\n }\n\n return metadata;\n}\n\n/**\n * Read the class names an export baked into the model metadata.\n *\n * Ultralytics writes `names` as the Python `repr` of a `dict[int, str]` — e.g.\n * `\"{0: 'deworm', 1: 'not_deworm'}\"`. The value is parsed structurally (never\n * evaluated), and anything unparseable, non-`dict`, or not keyed by contiguous\n * integers from zero is rejected whole rather than half-applied: a partial name\n * map would silently mislabel predictions.\n *\n * @param metadata A model's custom metadata map.\n * @returns Class names in class-id order, or `null` when the model carries no\n * usable `names` entry.\n */\nexport function modelNames(\n metadata: Readonly<Record<string, string>> | undefined,\n): readonly string[] | null {\n return parseNames(metadata?.names);\n}\n\n/**\n * Parse a `repr`-encoded `dict[int, str]` class map.\n *\n * Split out of {@link modelNames} because the same encoding is reused by a\n * fused pipeline, which carries one class map per stage and therefore cannot\n * store both under the single `names` key Ultralytics uses.\n *\n * @param encoded The encoded map — e.g. `\"{0: 'deworm', 1: 'not_deworm'}\"`.\n * @returns Class names in class-id order, or `null` when the value is missing,\n * unparseable, not a `dict`, or not keyed by contiguous integers from zero.\n */\nexport function parseNames(encoded: string | undefined): readonly string[] | null {\n const raw = encoded?.trim();\n if (!raw || !raw.startsWith(\"{\") || !raw.endsWith(\"}\")) return null;\n\n const body = raw.slice(1, -1).trim();\n if (!body) return null;\n\n const names = new Map<number, string>();\n const entryPattern = /(-?\\d+)\\s*:\\s*(?:'((?:[^'\\\\]|\\\\.)*)'|\"((?:[^\"\\\\]|\\\\.)*)\")/g;\n let consumed = 0;\n for (const match of body.matchAll(entryPattern)) {\n const id = Number(match[1]);\n const text = match[2] ?? match[3];\n if (!Number.isInteger(id) || text === undefined) return null;\n names.set(id, unescapeQuoted(text));\n consumed += match[0].length;\n }\n if (names.size === 0) return null;\n\n const separators = body.length - consumed;\n if (separators > names.size * 3) return null;\n\n const ordered: string[] = [];\n for (let id = 0; id < names.size; id += 1) {\n const name = names.get(id);\n if (name === undefined) return null;\n ordered.push(name);\n }\n return ordered;\n}\n\n/**\n * Resolve the backslash escapes Python's `repr` emits inside a quoted string.\n *\n * @param text The quoted string's contents, escapes intact.\n * @returns The same text with `\\\\`, `\\'`, `\\\"`, `\\n`, `\\r` and `\\t` resolved.\n */\nfunction unescapeQuoted(text: string): string {\n return text.replace(/\\\\(.)/g, (_, char: string) => {\n if (char === \"n\") return \"\\n\";\n if (char === \"r\") return \"\\r\";\n if (char === \"t\") return \"\\t\";\n return char;\n });\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("../core/exceptions.cjs"),t=require("../types.cjs"),n=require("../core/canvas.cjs");async function r(r){if(r instanceof t.RGBImage)return r;if(typeof ImageData<`u`&&r instanceof ImageData)return n.imageDataToRGB(r);if(typeof r==`string`)return i(r);if(typeof Blob<`u`&&r instanceof Blob)return a(r);if(typeof HTMLImageElement<`u`&&r instanceof HTMLImageElement)return await o(r),s(r,r.naturalWidth,r.naturalHeight);if(typeof HTMLCanvasElement<`u`&&r instanceof HTMLCanvasElement||typeof OffscreenCanvas<`u`&&r instanceof OffscreenCanvas||typeof ImageBitmap<`u`&&r instanceof ImageBitmap)return s(r,r.width,r.height);throw new e.ImageLoadError(`Unsupported image source type: ${Object.prototype.toString.call(r)}`)}async function i(t){let n;try{n=await fetch(t)}catch(n){throw new e.ImageLoadError(`Failed to fetch image from ${t}: ${n.message}`,{cause:n})}if(!n.ok)throw new e.ImageLoadError(`Failed to fetch image from ${t}: HTTP ${n.status} ${n.statusText}`);return a(await n.blob())}async function a(t){let n;try{n=await createImageBitmap(t)}catch(t){throw new e.ImageLoadError(`Failed to decode image blob: ${t.message}`,{cause:t})}try{return s(n,n.width,n.height)}finally{n.close()}}function o(t){return t.complete&&t.naturalWidth>0?Promise.resolve():new Promise((n,r)=>{let i=()=>{o(),n()},a=()=>{o(),r(new e.ImageLoadError(`Failed to load HTMLImageElement (load event errored)`))},o=()=>{t.removeEventListener(`load`,i),t.removeEventListener(`error`,a)};t.addEventListener(`load`,i,{once:!0}),t.addEventListener(`error`,a,{once:!0})})}function s(t,r,i){if(r===0||i===0)throw new e.ImageLoadError(`Cannot load image with zero dimension (${r}x${i}).`);let a=n.get2DContext(n.createCanvas(r,i));return a.drawImage(t,0,0),n.imageDataToRGB(a.getImageData(0,0,r,i))}exports.loadImage=r;
1
+ const e=require("../core/exceptions.cjs"),t=require("../types.cjs"),n=require("../core/canvas.cjs");async function r(r){if(r instanceof t.RGBImage)return r;if(typeof ImageData<`u`&&r instanceof ImageData)return n.imageDataToRGB(r);if(typeof r==`string`)return i(r);if(typeof Blob<`u`&&r instanceof Blob)return a(r);if(typeof HTMLImageElement<`u`&&r instanceof HTMLImageElement)return await o(r),s(r,r.naturalWidth,r.naturalHeight);if(typeof HTMLCanvasElement<`u`&&r instanceof HTMLCanvasElement||typeof OffscreenCanvas<`u`&&r instanceof OffscreenCanvas||typeof ImageBitmap<`u`&&r instanceof ImageBitmap)return s(r,r.width,r.height);throw new e.ImageLoadError(`Unsupported image source type: ${Object.prototype.toString.call(r)}`)}async function i(t){let n;try{n=await fetch(t)}catch(n){throw new e.ImageLoadError(`Failed to fetch image from ${t}: ${n.message}`,{cause:n})}if(!n.ok)throw new e.ImageLoadError(`Failed to fetch image from ${t}: HTTP ${n.status} ${n.statusText}`);return a(await n.blob())}async function a(t){let n;try{n=await createImageBitmap(t)}catch(t){throw new e.ImageLoadError(`Failed to decode image blob: ${t.message}`,{cause:t})}try{return s(n,n.width,n.height)}finally{n.close()}}function o(t){return t.complete&&t.naturalWidth>0?Promise.resolve():new Promise((n,r)=>{let i=()=>{o(),n()},a=()=>{o(),r(new e.ImageLoadError(`Failed to load HTMLImageElement (load event errored)`))},o=()=>{t.removeEventListener(`load`,i),t.removeEventListener(`error`,a)};t.addEventListener(`load`,i,{once:!0}),t.addEventListener(`error`,a,{once:!0})})}function s(t,r,i){if(r===0||i===0)throw new e.ImageLoadError(`Cannot load image with zero dimension (${r}x${i}).`);let a=n.createCanvas(r,i),o=n.get2DContext(a);o.drawImage(t,0,0);let s=o.getImageData(0,0,r,i);return n.imageDataToRGB(s)}exports.loadImage=r;
2
2
  //# sourceMappingURL=image.cjs.map