@codefast/ui 0.3.13-canary.3 → 0.3.13-canary.4

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 (367) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/components/accordion.d.mts +37 -0
  3. package/dist/components/accordion.mjs +53 -0
  4. package/dist/components/alert-dialog.d.mts +74 -0
  5. package/dist/components/alert-dialog.mjs +92 -0
  6. package/dist/components/alert.d.mts +30 -0
  7. package/dist/components/alert.mjs +49 -0
  8. package/dist/components/aspect-ratio.d.mts +10 -0
  9. package/dist/components/aspect-ratio.mjs +12 -0
  10. package/dist/components/avatar.d.mts +21 -0
  11. package/dist/components/avatar.mjs +28 -0
  12. package/dist/components/badge.d.mts +24 -0
  13. package/dist/components/badge.mjs +56 -0
  14. package/dist/components/breadcrumb.d.mts +44 -0
  15. package/dist/components/breadcrumb.mjs +67 -0
  16. package/dist/components/button-group.d.mts +34 -0
  17. package/dist/components/button-group.mjs +53 -0
  18. package/dist/components/button.d.mts +38 -0
  19. package/dist/components/button.mjs +99 -0
  20. package/dist/components/calendar.d.mts +27 -0
  21. package/dist/components/calendar.mjs +114 -0
  22. package/dist/components/card.d.mts +41 -0
  23. package/dist/components/card.mjs +55 -0
  24. package/dist/components/carousel.d.mts +68 -0
  25. package/dist/components/carousel.mjs +135 -0
  26. package/dist/components/chart.d.mts +93 -0
  27. package/dist/components/chart.mjs +189 -0
  28. package/dist/components/checkbox-cards.d.mts +17 -0
  29. package/dist/components/checkbox-cards.mjs +30 -0
  30. package/dist/components/checkbox-group.d.mts +16 -0
  31. package/dist/components/checkbox-group.mjs +27 -0
  32. package/dist/components/checkbox.d.mts +11 -0
  33. package/dist/components/checkbox.mjs +20 -0
  34. package/dist/components/collapsible.d.mts +18 -0
  35. package/dist/components/collapsible.mjs +24 -0
  36. package/dist/components/command.d.mts +57 -0
  37. package/dist/components/command.mjs +92 -0
  38. package/dist/components/context-menu.d.mts +91 -0
  39. package/dist/components/context-menu.mjs +122 -0
  40. package/dist/components/dialog.d.mts +65 -0
  41. package/dist/components/dialog.mjs +93 -0
  42. package/dist/components/drawer.d.mts +65 -0
  43. package/dist/components/drawer.mjs +78 -0
  44. package/dist/components/dropdown-menu.d.mts +92 -0
  45. package/dist/components/dropdown-menu.mjs +129 -0
  46. package/dist/components/empty.d.mts +44 -0
  47. package/dist/components/empty.mjs +64 -0
  48. package/dist/components/field.d.mts +79 -0
  49. package/dist/components/field.mjs +132 -0
  50. package/dist/components/form.d.mts +48 -0
  51. package/dist/components/form.mjs +92 -0
  52. package/dist/components/hover-card.d.mts +26 -0
  53. package/dist/components/hover-card.mjs +35 -0
  54. package/dist/components/input-group.d.mts +61 -0
  55. package/dist/components/input-group.mjs +142 -0
  56. package/dist/components/input-number.d.mts +28 -0
  57. package/dist/components/input-number.mjs +61 -0
  58. package/dist/components/input-otp.d.mts +29 -0
  59. package/dist/components/input-otp.mjs +48 -0
  60. package/dist/components/input-password.d.mts +13 -0
  61. package/dist/components/input-password.mjs +38 -0
  62. package/dist/components/input-search.d.mts +20 -0
  63. package/dist/components/input-search.mjs +50 -0
  64. package/dist/components/input.d.mts +11 -0
  65. package/dist/components/input.mjs +14 -0
  66. package/dist/components/item.d.mts +82 -0
  67. package/dist/components/item.mjs +137 -0
  68. package/dist/components/kbd.d.mts +15 -0
  69. package/dist/components/kbd.mjs +19 -0
  70. package/dist/components/label.d.mts +11 -0
  71. package/dist/components/label.mjs +14 -0
  72. package/dist/components/menubar.d.mts +100 -0
  73. package/dist/components/menubar.mjs +133 -0
  74. package/dist/components/native-select.d.mts +19 -0
  75. package/dist/components/native-select.mjs +34 -0
  76. package/dist/components/navigation-menu.d.mts +44 -0
  77. package/dist/components/navigation-menu.mjs +79 -0
  78. package/dist/components/pagination.d.mts +46 -0
  79. package/dist/components/pagination.mjs +71 -0
  80. package/dist/components/popover.d.mts +30 -0
  81. package/dist/components/popover.mjs +41 -0
  82. package/dist/components/progress-circle.d.mts +124 -0
  83. package/dist/components/progress-circle.mjs +120 -0
  84. package/dist/components/progress.d.mts +12 -0
  85. package/dist/components/progress.mjs +19 -0
  86. package/dist/components/{radio-cards.d.ts → radio-cards.d.mts} +10 -5
  87. package/dist/components/radio-cards.mjs +29 -0
  88. package/dist/components/radio-group.d.mts +16 -0
  89. package/dist/components/radio-group.mjs +25 -0
  90. package/dist/components/radio.d.mts +14 -0
  91. package/dist/components/radio.mjs +16 -0
  92. package/dist/components/resizable.d.mts +23 -0
  93. package/dist/components/resizable.mjs +32 -0
  94. package/dist/components/scroll-area.d.mts +40 -0
  95. package/dist/components/scroll-area.mjs +101 -0
  96. package/dist/components/select.d.mts +62 -0
  97. package/dist/components/select.mjs +101 -0
  98. package/dist/components/separator.d.mts +32 -0
  99. package/dist/components/separator.mjs +45 -0
  100. package/dist/components/sheet.d.mts +75 -0
  101. package/dist/components/sheet.mjs +134 -0
  102. package/dist/components/sidebar.d.mts +195 -0
  103. package/dist/components/sidebar.mjs +375 -0
  104. package/dist/components/skeleton.d.mts +10 -0
  105. package/dist/components/skeleton.mjs +12 -0
  106. package/dist/components/slider.d.mts +15 -0
  107. package/dist/components/slider.mjs +40 -0
  108. package/dist/components/sonner.d.mts +10 -0
  109. package/dist/components/sonner.mjs +21 -0
  110. package/dist/components/spinner.d.mts +14 -0
  111. package/dist/components/spinner.mjs +40 -0
  112. package/dist/components/switch.d.mts +11 -0
  113. package/dist/components/switch.mjs +18 -0
  114. package/dist/components/table.d.mts +45 -0
  115. package/dist/components/table.mjs +65 -0
  116. package/dist/components/tabs.d.mts +26 -0
  117. package/dist/components/tabs.mjs +35 -0
  118. package/dist/components/textarea.d.mts +10 -0
  119. package/dist/components/textarea.mjs +12 -0
  120. package/dist/components/toggle-group.d.mts +30 -0
  121. package/dist/components/toggle-group.mjs +53 -0
  122. package/dist/components/toggle.d.mts +28 -0
  123. package/dist/components/toggle.mjs +53 -0
  124. package/dist/components/tooltip.d.mts +30 -0
  125. package/dist/components/tooltip.mjs +42 -0
  126. package/dist/hooks/{use-animated-value.d.ts → use-animated-value.d.mts} +4 -2
  127. package/dist/hooks/use-animated-value.mjs +62 -0
  128. package/dist/hooks/{use-copy-to-clipboard.d.ts → use-copy-to-clipboard.d.mts} +11 -6
  129. package/dist/hooks/use-copy-to-clipboard.mjs +43 -0
  130. package/dist/hooks/{use-is-mobile.d.ts → use-is-mobile.d.mts} +4 -2
  131. package/dist/hooks/use-is-mobile.mjs +26 -0
  132. package/dist/hooks/{use-media-query.d.ts → use-media-query.d.mts} +4 -2
  133. package/dist/hooks/use-media-query.mjs +50 -0
  134. package/dist/hooks/{use-mutation-observer.d.ts → use-mutation-observer.d.mts} +6 -3
  135. package/dist/hooks/use-mutation-observer.mjs +41 -0
  136. package/dist/hooks/use-pagination.d.mts +44 -0
  137. package/dist/hooks/use-pagination.mjs +107 -0
  138. package/dist/index.d.mts +69 -0
  139. package/dist/index.mjs +69 -0
  140. package/dist/lib/utils.d.mts +13 -0
  141. package/dist/lib/utils.mjs +10 -0
  142. package/dist/node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/clsx.d.mts +6 -0
  143. package/dist/primitives/checkbox-group.d.mts +144 -0
  144. package/dist/primitives/checkbox-group.mjs +126 -0
  145. package/dist/primitives/input-number.d.mts +73 -0
  146. package/dist/primitives/input-number.mjs +514 -0
  147. package/dist/primitives/input.d.mts +72 -0
  148. package/dist/primitives/input.mjs +75 -0
  149. package/dist/primitives/progress-circle.d.mts +146 -0
  150. package/dist/primitives/progress-circle.mjs +178 -0
  151. package/package.json +164 -170
  152. package/dist/components/accordion.d.ts +0 -19
  153. package/dist/components/accordion.d.ts.map +0 -1
  154. package/dist/components/accordion.js +0 -26
  155. package/dist/components/alert-dialog.d.ts +0 -39
  156. package/dist/components/alert-dialog.d.ts.map +0 -1
  157. package/dist/components/alert-dialog.js +0 -39
  158. package/dist/components/alert.d.ts +0 -19
  159. package/dist/components/alert.d.ts.map +0 -1
  160. package/dist/components/alert.js +0 -41
  161. package/dist/components/aspect-ratio.d.ts +0 -7
  162. package/dist/components/aspect-ratio.d.ts.map +0 -1
  163. package/dist/components/aspect-ratio.js +0 -10
  164. package/dist/components/avatar.d.ts +0 -11
  165. package/dist/components/avatar.d.ts.map +0 -1
  166. package/dist/components/avatar.js +0 -17
  167. package/dist/components/badge.d.ts +0 -18
  168. package/dist/components/badge.d.ts.map +0 -1
  169. package/dist/components/badge.js +0 -59
  170. package/dist/components/breadcrumb.d.ts +0 -22
  171. package/dist/components/breadcrumb.d.ts.map +0 -1
  172. package/dist/components/breadcrumb.js +0 -31
  173. package/dist/components/button-group.d.ts +0 -20
  174. package/dist/components/button-group.d.ts.map +0 -1
  175. package/dist/components/button-group.js +0 -48
  176. package/dist/components/button.d.ts +0 -29
  177. package/dist/components/button.d.ts.map +0 -1
  178. package/dist/components/button.js +0 -92
  179. package/dist/components/calendar.d.ts +0 -13
  180. package/dist/components/calendar.d.ts.map +0 -1
  181. package/dist/components/calendar.js +0 -104
  182. package/dist/components/card.d.ts +0 -18
  183. package/dist/components/card.d.ts.map +0 -1
  184. package/dist/components/card.js +0 -27
  185. package/dist/components/carousel.d.ts +0 -38
  186. package/dist/components/carousel.d.ts.map +0 -1
  187. package/dist/components/carousel.js +0 -103
  188. package/dist/components/chart.d.ts +0 -58
  189. package/dist/components/chart.d.ts.map +0 -1
  190. package/dist/components/chart.js +0 -198
  191. package/dist/components/checkbox-cards.d.ts +0 -11
  192. package/dist/components/checkbox-cards.d.ts.map +0 -1
  193. package/dist/components/checkbox-cards.js +0 -16
  194. package/dist/components/checkbox-group.d.ts +0 -9
  195. package/dist/components/checkbox-group.d.ts.map +0 -1
  196. package/dist/components/checkbox-group.js +0 -15
  197. package/dist/components/checkbox.d.ts +0 -7
  198. package/dist/components/checkbox.d.ts.map +0 -1
  199. package/dist/components/checkbox.js +0 -12
  200. package/dist/components/collapsible.d.ts +0 -11
  201. package/dist/components/collapsible.d.ts.map +0 -1
  202. package/dist/components/collapsible.js +0 -16
  203. package/dist/components/command.d.ts +0 -26
  204. package/dist/components/command.d.ts.map +0 -1
  205. package/dist/components/command.js +0 -41
  206. package/dist/components/context-menu.d.ts +0 -42
  207. package/dist/components/context-menu.d.ts.map +0 -1
  208. package/dist/components/context-menu.js +0 -54
  209. package/dist/components/dialog.d.ts +0 -35
  210. package/dist/components/dialog.d.ts.map +0 -1
  211. package/dist/components/dialog.js +0 -41
  212. package/dist/components/drawer.d.ts +0 -34
  213. package/dist/components/drawer.d.ts.map +0 -1
  214. package/dist/components/drawer.js +0 -36
  215. package/dist/components/dropdown-menu.d.ts +0 -42
  216. package/dist/components/dropdown-menu.d.ts.map +0 -1
  217. package/dist/components/dropdown-menu.js +0 -54
  218. package/dist/components/empty.d.ts +0 -23
  219. package/dist/components/empty.d.ts.map +0 -1
  220. package/dist/components/empty.js +0 -47
  221. package/dist/components/field.d.ts +0 -42
  222. package/dist/components/field.d.ts.map +0 -1
  223. package/dist/components/field.js +0 -85
  224. package/dist/components/form.d.ts +0 -27
  225. package/dist/components/form.d.ts.map +0 -1
  226. package/dist/components/form.js +0 -76
  227. package/dist/components/hover-card.d.ts +0 -13
  228. package/dist/components/hover-card.d.ts.map +0 -1
  229. package/dist/components/hover-card.js +0 -20
  230. package/dist/components/input-group.d.ts +0 -37
  231. package/dist/components/input-group.d.ts.map +0 -1
  232. package/dist/components/input-group.js +0 -127
  233. package/dist/components/input-number.d.ts +0 -8
  234. package/dist/components/input-number.d.ts.map +0 -1
  235. package/dist/components/input-number.js +0 -20
  236. package/dist/components/input-otp.d.ts +0 -16
  237. package/dist/components/input-otp.d.ts.map +0 -1
  238. package/dist/components/input-otp.js +0 -25
  239. package/dist/components/input-password.d.ts +0 -7
  240. package/dist/components/input-password.d.ts.map +0 -1
  241. package/dist/components/input-password.js +0 -17
  242. package/dist/components/input-search.d.ts +0 -11
  243. package/dist/components/input-search.d.ts.map +0 -1
  244. package/dist/components/input-search.js +0 -22
  245. package/dist/components/input.d.ts +0 -6
  246. package/dist/components/input.d.ts.map +0 -1
  247. package/dist/components/input.js +0 -10
  248. package/dist/components/item.d.ts +0 -46
  249. package/dist/components/item.d.ts.map +0 -1
  250. package/dist/components/item.js +0 -94
  251. package/dist/components/kbd.d.ts +0 -8
  252. package/dist/components/kbd.d.ts.map +0 -1
  253. package/dist/components/kbd.js +0 -12
  254. package/dist/components/label.d.ts +0 -7
  255. package/dist/components/label.d.ts.map +0 -1
  256. package/dist/components/label.js +0 -11
  257. package/dist/components/menubar.d.ts +0 -44
  258. package/dist/components/menubar.d.ts.map +0 -1
  259. package/dist/components/menubar.js +0 -57
  260. package/dist/components/native-select.d.ts +0 -10
  261. package/dist/components/native-select.d.ts.map +0 -1
  262. package/dist/components/native-select.js +0 -16
  263. package/dist/components/navigation-menu.d.ts +0 -21
  264. package/dist/components/navigation-menu.d.ts.map +0 -1
  265. package/dist/components/navigation-menu.js +0 -43
  266. package/dist/components/pagination.d.ts +0 -26
  267. package/dist/components/pagination.d.ts.map +0 -1
  268. package/dist/components/pagination.js +0 -29
  269. package/dist/components/popover.d.ts +0 -15
  270. package/dist/components/popover.d.ts.map +0 -1
  271. package/dist/components/popover.js +0 -23
  272. package/dist/components/progress-circle.d.ts +0 -107
  273. package/dist/components/progress-circle.d.ts.map +0 -1
  274. package/dist/components/progress-circle.js +0 -83
  275. package/dist/components/progress.d.ts +0 -7
  276. package/dist/components/progress.d.ts.map +0 -1
  277. package/dist/components/progress.js +0 -13
  278. package/dist/components/radio-cards.d.ts.map +0 -1
  279. package/dist/components/radio-cards.js +0 -15
  280. package/dist/components/radio-group.d.ts +0 -9
  281. package/dist/components/radio-group.d.ts.map +0 -1
  282. package/dist/components/radio-group.js +0 -14
  283. package/dist/components/radio.d.ts +0 -8
  284. package/dist/components/radio.d.ts.map +0 -1
  285. package/dist/components/radio.js +0 -11
  286. package/dist/components/resizable.d.ts +0 -13
  287. package/dist/components/resizable.d.ts.map +0 -1
  288. package/dist/components/resizable.js +0 -18
  289. package/dist/components/scroll-area.d.ts +0 -28
  290. package/dist/components/scroll-area.d.ts.map +0 -1
  291. package/dist/components/scroll-area.js +0 -77
  292. package/dist/components/select.d.ts +0 -29
  293. package/dist/components/select.d.ts.map +0 -1
  294. package/dist/components/select.js +0 -49
  295. package/dist/components/separator.d.ts +0 -23
  296. package/dist/components/separator.d.ts.map +0 -1
  297. package/dist/components/separator.js +0 -36
  298. package/dist/components/sheet.d.ts +0 -43
  299. package/dist/components/sheet.d.ts.map +0 -1
  300. package/dist/components/sheet.js +0 -90
  301. package/dist/components/sidebar.d.ts +0 -102
  302. package/dist/components/sidebar.d.ts.map +0 -1
  303. package/dist/components/sidebar.js +0 -241
  304. package/dist/components/skeleton.d.ts +0 -6
  305. package/dist/components/skeleton.d.ts.map +0 -1
  306. package/dist/components/skeleton.js +0 -9
  307. package/dist/components/slider.d.ts +0 -7
  308. package/dist/components/slider.d.ts.map +0 -1
  309. package/dist/components/slider.js +0 -18
  310. package/dist/components/sonner.d.ts +0 -8
  311. package/dist/components/sonner.d.ts.map +0 -1
  312. package/dist/components/sonner.js +0 -18
  313. package/dist/components/spinner.d.ts +0 -8
  314. package/dist/components/spinner.d.ts.map +0 -1
  315. package/dist/components/spinner.js +0 -27
  316. package/dist/components/switch.d.ts +0 -7
  317. package/dist/components/switch.d.ts.map +0 -1
  318. package/dist/components/switch.js +0 -11
  319. package/dist/components/table.d.ts +0 -20
  320. package/dist/components/table.d.ts.map +0 -1
  321. package/dist/components/table.js +0 -30
  322. package/dist/components/tabs.d.ts +0 -13
  323. package/dist/components/tabs.d.ts.map +0 -1
  324. package/dist/components/tabs.js +0 -20
  325. package/dist/components/textarea.d.ts +0 -6
  326. package/dist/components/textarea.d.ts.map +0 -1
  327. package/dist/components/textarea.js +0 -9
  328. package/dist/components/toggle-group.d.ts +0 -16
  329. package/dist/components/toggle-group.d.ts.map +0 -1
  330. package/dist/components/toggle-group.js +0 -35
  331. package/dist/components/toggle.d.ts +0 -21
  332. package/dist/components/toggle.d.ts.map +0 -1
  333. package/dist/components/toggle.js +0 -49
  334. package/dist/components/tooltip.d.ts +0 -15
  335. package/dist/components/tooltip.d.ts.map +0 -1
  336. package/dist/components/tooltip.js +0 -23
  337. package/dist/hooks/use-animated-value.d.ts.map +0 -1
  338. package/dist/hooks/use-animated-value.js +0 -71
  339. package/dist/hooks/use-copy-to-clipboard.d.ts.map +0 -1
  340. package/dist/hooks/use-copy-to-clipboard.js +0 -46
  341. package/dist/hooks/use-is-mobile.d.ts.map +0 -1
  342. package/dist/hooks/use-is-mobile.js +0 -23
  343. package/dist/hooks/use-media-query.d.ts.map +0 -1
  344. package/dist/hooks/use-media-query.js +0 -53
  345. package/dist/hooks/use-mutation-observer.d.ts.map +0 -1
  346. package/dist/hooks/use-mutation-observer.js +0 -40
  347. package/dist/hooks/use-pagination.d.ts +0 -37
  348. package/dist/hooks/use-pagination.d.ts.map +0 -1
  349. package/dist/hooks/use-pagination.js +0 -107
  350. package/dist/index.d.ts +0 -131
  351. package/dist/index.d.ts.map +0 -1
  352. package/dist/index.js +0 -68
  353. package/dist/lib/utils.d.ts +0 -10
  354. package/dist/lib/utils.d.ts.map +0 -1
  355. package/dist/lib/utils.js +0 -10
  356. package/dist/primitives/checkbox-group.d.ts +0 -123
  357. package/dist/primitives/checkbox-group.d.ts.map +0 -1
  358. package/dist/primitives/checkbox-group.js +0 -112
  359. package/dist/primitives/input-number.d.ts +0 -63
  360. package/dist/primitives/input-number.d.ts.map +0 -1
  361. package/dist/primitives/input-number.js +0 -458
  362. package/dist/primitives/input.d.ts +0 -67
  363. package/dist/primitives/input.d.ts.map +0 -1
  364. package/dist/primitives/input.js +0 -76
  365. package/dist/primitives/progress-circle.d.ts +0 -116
  366. package/dist/primitives/progress-circle.d.ts.map +0 -1
  367. package/dist/primitives/progress-circle.js +0 -163
@@ -0,0 +1,514 @@
1
+ import { Field as InputField, Input, createInputScope } from "./input.mjs";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useCallback, useEffect, useMemo, useRef } from "react";
4
+ import { createContextScope } from "@radix-ui/react-context";
5
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
6
+ import { composeEventHandlers } from "@radix-ui/primitive";
7
+ //#region src/primitives/input-number.tsx
8
+ /**
9
+ * The name of the InputNumber component constant.
10
+ */
11
+ const NUMBER_INPUT_NAME = "InputNumber";
12
+ const [createInputNumberContext, createInputNumberScope] = createContextScope(NUMBER_INPUT_NAME, [createInputScope]);
13
+ const useInputScope = createInputScope();
14
+ const [InputNumberContextProvider, useInputNumberContext] = createInputNumberContext(NUMBER_INPUT_NAME);
15
+ function InputNumber(numberInputProps) {
16
+ const { __scopeInputNumber, ariaDecrementLabel, ariaIncrementLabel, defaultValue, formatOptions = {
17
+ minimumFractionDigits: 0,
18
+ style: "decimal"
19
+ }, id, locale, max, min, onChange, step = 1, value: valueProperty, ...props } = numberInputProps;
20
+ /** Scope for the input component */
21
+ const inputScope = useInputScope(__scopeInputNumber);
22
+ /** Reference to the input element */
23
+ const inputRef = useRef(null);
24
+ /** Controlled or uncontrolled value state */
25
+ const [value, setValue] = useControllableState({
26
+ defaultProp: defaultValue,
27
+ onChange,
28
+ prop: valueProperty
29
+ });
30
+ /** Separators used for number formatting based on locale */
31
+ const { decimalSeparator, thousandSeparator } = useMemo(() => getNumberFormatSeparators(locale), [locale]);
32
+ /**
33
+ * Formats a number value into a string representation
34
+ * @param inputValue - The number to format
35
+ * @returns A formatted string representation of the number
36
+ */
37
+ const formatValue = useCallback((inputValue) => {
38
+ if (inputValue === void 0 || Number.isNaN(inputValue)) return "";
39
+ return new Intl.NumberFormat(locale, formatOptions).format(inputValue);
40
+ }, [formatOptions, locale]);
41
+ /**
42
+ * Parses a string or number input into a normalized number value
43
+ * @param inputValue - The value to parse
44
+ * @returns The parsed number value, clamped between min and max
45
+ */
46
+ const parseValue = useCallback((inputValue) => {
47
+ if (typeof inputValue === "number") return clamp(inputValue, min, max);
48
+ if (typeof inputValue !== "string") return NaN;
49
+ const cleanedValue = inputValue.trim().replaceAll(/[^\d.,\-()]/g, "");
50
+ if (cleanedValue === "") return NaN;
51
+ const normalizedValue = normalizeInputValue(cleanedValue, thousandSeparator, decimalSeparator);
52
+ let parsedValue = Number.parseFloat(normalizedValue);
53
+ if (formatOptions.style === "percent") parsedValue /= 100;
54
+ return Number.isNaN(parsedValue) ? 0 : clamp(parsedValue, min, max);
55
+ }, [
56
+ decimalSeparator,
57
+ formatOptions.style,
58
+ max,
59
+ min,
60
+ thousandSeparator
61
+ ]);
62
+ /**
63
+ * Changes the current value based on a provided operation
64
+ * @param operation - Function that takes the current value and returns a new value
65
+ */
66
+ const changeNumberValue = useCallback((operation) => {
67
+ const inputElement = inputRef.current;
68
+ if (!inputElement || props.disabled || props.readOnly) return;
69
+ const newValue = clamp(operation(parseValue(inputElement.value) || 0), min, max);
70
+ inputElement.value = formatValue(newValue);
71
+ setValue(newValue);
72
+ }, [
73
+ props.disabled,
74
+ formatValue,
75
+ max,
76
+ min,
77
+ parseValue,
78
+ props.readOnly,
79
+ setValue
80
+ ]);
81
+ /**
82
+ * Increments the current value by the step amount
83
+ */
84
+ const handleIncrement = useCallback(() => {
85
+ changeNumberValue((number) => number + step);
86
+ }, [changeNumberValue, step]);
87
+ /**
88
+ * Decrements the current value by the step amount
89
+ */
90
+ const handleDecrement = useCallback(() => {
91
+ changeNumberValue((number) => number - step);
92
+ }, [changeNumberValue, step]);
93
+ /**
94
+ * Sets the value to the maximum allowed
95
+ */
96
+ const handleIncrementToMax = useCallback(() => {
97
+ changeNumberValue((number) => max ?? number + step);
98
+ }, [
99
+ changeNumberValue,
100
+ max,
101
+ step
102
+ ]);
103
+ /**
104
+ * Sets the value to the minimum allowed
105
+ */
106
+ const handleDecrementToMin = useCallback(() => {
107
+ changeNumberValue((number) => min ?? number - step);
108
+ }, [
109
+ changeNumberValue,
110
+ min,
111
+ step
112
+ ]);
113
+ return /* @__PURE__ */ jsx(InputNumberContextProvider, {
114
+ ariaDecrementLabel,
115
+ ariaIncrementLabel,
116
+ defaultValue,
117
+ disabled: props.disabled,
118
+ formatOptions,
119
+ formatValue,
120
+ id,
121
+ inputRef,
122
+ max,
123
+ min,
124
+ parseValue,
125
+ readOnly: props.readOnly,
126
+ scope: __scopeInputNumber,
127
+ value,
128
+ onChange: setValue,
129
+ onDecrement: handleDecrement,
130
+ onDecrementToMin: handleDecrementToMin,
131
+ onIncrement: handleIncrement,
132
+ onIncrementToMax: handleIncrementToMax,
133
+ children: /* @__PURE__ */ jsx(Input, {
134
+ ...inputScope,
135
+ ...props
136
+ })
137
+ });
138
+ }
139
+ /**
140
+ * The name of the InputNumberField component constant.
141
+ */
142
+ const NUMBER_INPUT_FIELD_NAME = "InputNumberField";
143
+ function InputNumberField({ __scopeInputNumber, onBlur, onKeyDown, ...props }) {
144
+ const inputScope = useInputScope(__scopeInputNumber);
145
+ const { defaultValue, disabled, formatValue, id, inputRef, max, min, onChange, onDecrement, onDecrementToMin, onIncrement, onIncrementToMax, parseValue, readOnly, step, value } = useInputNumberContext(NUMBER_INPUT_FIELD_NAME, __scopeInputNumber);
146
+ /**
147
+ * Handles the blur event to format the value of the input.
148
+ *
149
+ * @param event - The blur event triggered when the input loses focus.
150
+ */
151
+ const handleBlur = useCallback((event) => {
152
+ const numericValue = parseValue(event.target.value);
153
+ const formattedValue = formatValue(numericValue);
154
+ if (formattedValue !== event.target.value) event.target.value = formattedValue;
155
+ onChange(numericValue);
156
+ }, [
157
+ formatValue,
158
+ onChange,
159
+ parseValue
160
+ ]);
161
+ /**
162
+ * Handles keydown events to increment, decrement, or perform other actions.
163
+ *
164
+ * @param event - The keyboard event triggered by key presses.
165
+ */
166
+ const handleKeyDown = useCallback((event) => {
167
+ switch (event.key) {
168
+ case "ArrowUp":
169
+ onIncrement();
170
+ event.preventDefault();
171
+ break;
172
+ case "PageUp":
173
+ onIncrementToMax();
174
+ event.preventDefault();
175
+ break;
176
+ case "ArrowDown":
177
+ onDecrement();
178
+ event.preventDefault();
179
+ break;
180
+ case "PageDown":
181
+ onDecrementToMin();
182
+ event.preventDefault();
183
+ break;
184
+ default: break;
185
+ }
186
+ }, [
187
+ onIncrement,
188
+ onIncrementToMax,
189
+ onDecrement,
190
+ onDecrementToMin
191
+ ]);
192
+ /**
193
+ * Prevents invalid keyboard input for the numeric input field.
194
+ *
195
+ * @param event - The keyboard event to handle.
196
+ */
197
+ const handleKeyDownPrevent = useCallback((event) => {
198
+ switch (event.key) {
199
+ case "ArrowUp":
200
+ case "ArrowDown":
201
+ case "ArrowLeft":
202
+ case "ArrowRight":
203
+ case "PageUp":
204
+ case "PageDown":
205
+ case "Tab":
206
+ case "Escape":
207
+ case "Enter":
208
+ case "Backspace":
209
+ case "Delete":
210
+ case "Home":
211
+ case "End":
212
+ case ".":
213
+ case ",":
214
+ case "-":
215
+ case "%": return;
216
+ default:
217
+ if (isNumberKey(event.key) || isModifierKey(event) || isFunctionKey(event.key)) return;
218
+ event.preventDefault();
219
+ }
220
+ }, []);
221
+ /**
222
+ * Handles the Enter key to format the value of the input.
223
+ *
224
+ * @param event - The keyboard event triggered by pressing Enter.
225
+ */
226
+ const handleKeyDownEnter = useCallback((event) => {
227
+ const inputElement = inputRef.current;
228
+ if (event.key !== "Enter" || !inputElement) return;
229
+ const numericValue = parseValue(inputElement.value);
230
+ const formattedValue = formatValue(numericValue);
231
+ if (formattedValue !== inputElement.value) inputElement.value = formattedValue;
232
+ onChange(numericValue);
233
+ }, [
234
+ formatValue,
235
+ inputRef,
236
+ onChange,
237
+ parseValue
238
+ ]);
239
+ /**
240
+ * Creates a combined keydown event handler that processes keyboard events in sequence.
241
+ *
242
+ * The handler chain executes in the following order:
243
+ * 1. User-provided onKeyDown handler (if any)
244
+ * 2. handleKeyDownPrevent - Prevents non-numeric input
245
+ * 3. handleKeyDown - Handles arrow keys and page up/down for value adjustments
246
+ * 4. handleKeyDownEnter - Handles Enter key press to format and update the value
247
+ *
248
+ * @returns A composed event handler function for the onKeyDown event
249
+ */
250
+ const combinedKeyDownHandler = useCallback((event) => {
251
+ composeEventHandlers(onKeyDown, chain(handleKeyDownPrevent, handleKeyDown, handleKeyDownEnter))(event);
252
+ }, [
253
+ onKeyDown,
254
+ handleKeyDown,
255
+ handleKeyDownEnter,
256
+ handleKeyDownPrevent
257
+ ]);
258
+ /**
259
+ * Adds a listener to handle wheel events for incrementing or decrementing the value.
260
+ */
261
+ useEffect(() => {
262
+ const handleWheel = (event) => {
263
+ const inputElement = inputRef.current;
264
+ if (!inputElement || disabled || readOnly || document.activeElement !== inputElement) return;
265
+ event.preventDefault();
266
+ if (event.deltaY > 0) onIncrement();
267
+ else onDecrement();
268
+ };
269
+ const inputElement = inputRef.current;
270
+ inputElement?.addEventListener("wheel", handleWheel);
271
+ return () => {
272
+ inputElement?.removeEventListener("wheel", handleWheel);
273
+ };
274
+ }, [
275
+ onIncrement,
276
+ onDecrement,
277
+ inputRef,
278
+ disabled,
279
+ readOnly
280
+ ]);
281
+ /**
282
+ * Updates the input field's value when it changes in the context.
283
+ */
284
+ useEffect(() => {
285
+ const inputElement = inputRef.current;
286
+ if (inputElement && inputElement !== document.activeElement) inputElement.value = formatValue(value);
287
+ }, [
288
+ formatValue,
289
+ inputRef,
290
+ value
291
+ ]);
292
+ /**
293
+ * Adds a listener to handle form reset events by clearing the input value.
294
+ */
295
+ useEffect(() => {
296
+ const inputElement = inputRef.current;
297
+ if (!inputElement) return;
298
+ const handleReset = () => {
299
+ onChange(parseValue(defaultValue));
300
+ };
301
+ const form = inputElement.form;
302
+ form?.addEventListener("reset", handleReset);
303
+ return () => {
304
+ form?.removeEventListener("reset", handleReset);
305
+ };
306
+ }, [
307
+ defaultValue,
308
+ inputRef,
309
+ onChange,
310
+ parseValue
311
+ ]);
312
+ return /* @__PURE__ */ jsx(InputField, {
313
+ ref: inputRef,
314
+ defaultValue: formatValue(value),
315
+ disabled,
316
+ id,
317
+ inputMode: "decimal",
318
+ max,
319
+ min,
320
+ readOnly,
321
+ step,
322
+ onBlur: composeEventHandlers(onBlur, handleBlur),
323
+ onKeyDown: combinedKeyDownHandler,
324
+ ...inputScope,
325
+ ...props
326
+ });
327
+ }
328
+ /**
329
+ * The name of the NumberStepperButton component constant.
330
+ */
331
+ const NUMBER_STEPPER_BUTTON_NAME = "NumberStepperButton";
332
+ function NumberStepperButton({ __scopeInputNumber, operation, ...props }) {
333
+ const { ariaDecrementLabel, ariaIncrementLabel, disabled, id, max, min, onDecrement, onIncrement, value } = useInputNumberContext(NUMBER_STEPPER_BUTTON_NAME, __scopeInputNumber);
334
+ const isDisabled = useMemo(() => {
335
+ return (disabled ?? (min !== void 0 && value !== void 0 && value <= min)) || max !== void 0 && value !== void 0 && value >= max;
336
+ }, [
337
+ min,
338
+ max,
339
+ value,
340
+ disabled
341
+ ]);
342
+ /**
343
+ * Ref to store a timeout ID for managing repeated button actions.
344
+ */
345
+ const timeoutIdRef = useRef(null);
346
+ /**
347
+ * Starts a repeated action at a regular interval.
348
+ * The action begins immediately and then continues with a delay.
349
+ *
350
+ * @param callback - The callback function to execute repeatedly.
351
+ */
352
+ const startActionInterval = useCallback((callback) => {
353
+ const interval = 100;
354
+ const repeatAction = () => {
355
+ callback();
356
+ timeoutIdRef.current = setTimeout(repeatAction, interval);
357
+ };
358
+ callback();
359
+ timeoutIdRef.current = setTimeout(repeatAction, interval * 2);
360
+ }, []);
361
+ /**
362
+ * Clears any ongoing action intervals.
363
+ */
364
+ const clearActionInterval = useCallback(() => {
365
+ if (timeoutIdRef.current) {
366
+ clearTimeout(timeoutIdRef.current);
367
+ timeoutIdRef.current = null;
368
+ }
369
+ }, []);
370
+ /**
371
+ * Handles pointer down events and triggers the appropriate action
372
+ * (`increment` or `decrement`).
373
+ */
374
+ const handlePointerDown = useCallback(() => {
375
+ startActionInterval(operation === "increment" ? onIncrement : onDecrement);
376
+ }, [
377
+ onDecrement,
378
+ onIncrement,
379
+ operation,
380
+ startActionInterval
381
+ ]);
382
+ /**
383
+ * Prevents the context menu from displaying when the button is right-clicked.
384
+ *
385
+ * @param event - The mouse event triggered by the right-click.
386
+ */
387
+ const handleContextMenu = useCallback((event) => {
388
+ event.preventDefault();
389
+ }, []);
390
+ /**
391
+ * Handles keyboard events to support activation of the button using
392
+ * keyboard navigation (Enter or Space).
393
+ *
394
+ * @param event - The keyboard event with the triggered key.
395
+ */
396
+ const handleKeyDown = useCallback((event) => {
397
+ if (event.key === "Enter" || event.key === " ") {
398
+ event.preventDefault();
399
+ (operation === "increment" ? onIncrement : onDecrement)();
400
+ }
401
+ }, [
402
+ onDecrement,
403
+ onIncrement,
404
+ operation
405
+ ]);
406
+ return /* @__PURE__ */ jsx("button", {
407
+ "aria-controls": id,
408
+ "aria-label": operation === "increment" ? ariaIncrementLabel : ariaDecrementLabel,
409
+ "aria-live": "polite",
410
+ disabled: isDisabled,
411
+ type: "button",
412
+ onContextMenu: handleContextMenu,
413
+ onKeyDown: handleKeyDown,
414
+ onPointerCancel: clearActionInterval,
415
+ onPointerDown: handlePointerDown,
416
+ onPointerLeave: clearActionInterval,
417
+ onPointerUp: clearActionInterval,
418
+ ...props
419
+ });
420
+ }
421
+ function InputNumberIncrementButton(props) {
422
+ return /* @__PURE__ */ jsx(NumberStepperButton, {
423
+ operation: "increment",
424
+ ...props
425
+ });
426
+ }
427
+ function InputNumberDecrementButton(props) {
428
+ return /* @__PURE__ */ jsx(NumberStepperButton, {
429
+ operation: "decrement",
430
+ ...props
431
+ });
432
+ }
433
+ /**
434
+ * Chains multiple callbacks into a single function
435
+ *
436
+ * @param callbacks - Array of callback functions that will be executed in order
437
+ * @returns A single function that executes all callbacks
438
+ */
439
+ function chain(...callbacks) {
440
+ return (...args) => {
441
+ for (const callback of callbacks) callback(...args);
442
+ };
443
+ }
444
+ /**
445
+ * Extracts decimal and a thousand separators from a given locale's number format
446
+ *
447
+ * @param locale - The locale string to use for number formatting (e.g., 'en-US', 'de-DE')
448
+ * @returns Object containing decimal and a thousand separators
449
+ */
450
+ function getNumberFormatSeparators(locale) {
451
+ const parts = new Intl.NumberFormat(locale).formatToParts(12345.6);
452
+ let thousandSeparator = "";
453
+ let decimalSeparator = "";
454
+ for (const part of parts) {
455
+ if (part.type === "group") thousandSeparator = part.value;
456
+ if (part.type === "decimal") decimalSeparator = part.value;
457
+ if (thousandSeparator && decimalSeparator) break;
458
+ }
459
+ return {
460
+ decimalSeparator,
461
+ thousandSeparator
462
+ };
463
+ }
464
+ /**
465
+ * Normalizes an input value by removing formatting characters
466
+ *
467
+ * @param value - The input string to normalize
468
+ * @param thousandSeparator - The thousand-separator character to remove
469
+ * @param decimalSeparator - The decimal separator to convert to standard dot notation
470
+ * @returns Normalized string value ready for numeric conversion
471
+ */
472
+ function normalizeInputValue(value, thousandSeparator, decimalSeparator) {
473
+ return value.replaceAll(new RegExp(`\\${thousandSeparator}`, "g"), "").replace(new RegExp(`\\${decimalSeparator}`), ".").replaceAll(/[()]/g, "-");
474
+ }
475
+ /**
476
+ * Checks if a keyboard event includes modifier keys (Ctrl, Alt, Meta, Shift)
477
+ *
478
+ * @param event - The keyboard event to check
479
+ * @returns True if any modifier key is pressed
480
+ */
481
+ function isModifierKey(event) {
482
+ return event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
483
+ }
484
+ /**
485
+ * Determines if a key is a function key (F1-F12)
486
+ *
487
+ * @param key - The key name to check
488
+ * @returns True if the key is a function key
489
+ */
490
+ function isFunctionKey(key) {
491
+ return key.startsWith("F") && key.length > 1;
492
+ }
493
+ /**
494
+ * Checks if a key represents a number (0-9)
495
+ *
496
+ * @param key - The key name to check
497
+ * @returns True if the key represents a number
498
+ */
499
+ function isNumberKey(key) {
500
+ return !Number.isNaN(Number(key));
501
+ }
502
+ /**
503
+ * Clamps a numeric value between a minimum and maximum
504
+ *
505
+ * @param value - The value to clamp
506
+ * @param min - The minimum allowed value (defaults to \-Infinity)
507
+ * @param max - The maximum allowed value (defaults to Infinity)
508
+ * @returns The clamped value
509
+ */
510
+ function clamp(value, min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY) {
511
+ return Math.min(Math.max(value, min), max);
512
+ }
513
+ //#endregion
514
+ export { InputNumberDecrementButton as DecrementButton, InputNumberDecrementButton, InputNumberField as Field, InputNumberField, InputNumberIncrementButton as IncrementButton, InputNumberIncrementButton, InputNumber, InputNumber as Root, createInputNumberScope };
@@ -0,0 +1,72 @@
1
+ import { ComponentProps, JSX, PropsWithChildren, ReactNode } from "react";
2
+ import * as _$_radix_ui_react_context0 from "@radix-ui/react-context";
3
+ import { Scope } from "@radix-ui/react-context";
4
+
5
+ //#region src/primitives/input.d.ts
6
+ /**
7
+ * Type for adding scope to component props
8
+ */
9
+ type ScopedProps<P> = P & {
10
+ /**
11
+ * Scope for the Input component context
12
+ */
13
+ __scopeInput?: Scope;
14
+ };
15
+ declare const createInputScope: _$_radix_ui_react_context0.CreateScope;
16
+ /**
17
+ * Props for styling and appearance of the Input component
18
+ */
19
+ interface InputVisualProps {
20
+ /**
21
+ * CSS class name for the input container
22
+ */
23
+ className?: string;
24
+ /**
25
+ * Element to display before the input
26
+ */
27
+ prefix?: ReactNode;
28
+ /**
29
+ * Custom spinner element for loading state
30
+ */
31
+ spinner?: ReactNode;
32
+ /**
33
+ * Element to display after the input
34
+ */
35
+ suffix?: ReactNode;
36
+ }
37
+ /**
38
+ * Props for the behavior and state of the Input component
39
+ */
40
+ interface InputBehaviorProps {
41
+ /**
42
+ * Whether the input is disabled
43
+ */
44
+ disabled?: boolean;
45
+ /**
46
+ * Position of the loading spinner - either before or after the input
47
+ */
48
+ loaderPosition?: "prefix" | "suffix";
49
+ /**
50
+ * Whether the input is in the loading state
51
+ */
52
+ loading?: boolean;
53
+ /**
54
+ * Whether the input is in read-only mode
55
+ */
56
+ readOnly?: boolean;
57
+ }
58
+ /**
59
+ * Combined props for the Input component
60
+ */
61
+ type InputProps = PropsWithChildren<InputBehaviorProps & InputVisualProps>;
62
+ declare function Input(inputProps: ScopedProps<InputProps>): JSX.Element;
63
+ /**
64
+ * Props for the InputField component
65
+ */
66
+ type InputFieldProps = ComponentProps<"input">;
67
+ declare function InputField({
68
+ __scopeInput,
69
+ ...props
70
+ }: ScopedProps<InputFieldProps>): JSX.Element;
71
+ //#endregion
72
+ export { InputField as Field, InputField, Input, Input as Root, type InputFieldProps, type InputProps, createInputScope };
@@ -0,0 +1,75 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useRef } from "react";
3
+ import { createContextScope } from "@radix-ui/react-context";
4
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
5
+ //#region src/primitives/input.tsx
6
+ const INPUT_NAME = "Input";
7
+ const [createInputContext, createInputScope] = createContextScope(INPUT_NAME);
8
+ const [InputContextProvider, useInputContext] = createInputContext(INPUT_NAME);
9
+ function Input(inputProps) {
10
+ const { __scopeInput, children, disabled, loaderPosition = "prefix", loading, prefix, readOnly, spinner, suffix, ...props } = inputProps;
11
+ /**
12
+ * Reference to the input element
13
+ */
14
+ const inputRef = useRef(null);
15
+ /**
16
+ * Handles pointer down events on the input container
17
+ * Focuses the input element when clicking on the container
18
+ *
19
+ * @param event - The pointer event object
20
+ */
21
+ const handlePointerDown = (event) => {
22
+ const target = event.target;
23
+ if (target.tagName.toLowerCase() === "input" || target.closest("input, a, button")) {
24
+ event.stopPropagation();
25
+ return;
26
+ }
27
+ const inputElement = inputRef.current;
28
+ if (!inputElement) return;
29
+ if (document.activeElement === inputElement) {
30
+ event.preventDefault();
31
+ return;
32
+ }
33
+ requestAnimationFrame(() => {
34
+ if (inputElement.type === "file") {
35
+ inputElement.click();
36
+ return;
37
+ }
38
+ if (document.activeElement !== inputElement) inputElement.focus();
39
+ });
40
+ };
41
+ return /* @__PURE__ */ jsx(InputContextProvider, {
42
+ disabled,
43
+ inputRef,
44
+ readOnly,
45
+ scope: __scopeInput,
46
+ children: /* @__PURE__ */ jsxs("div", {
47
+ "data-disabled": disabled,
48
+ "data-readonly": readOnly,
49
+ role: "presentation",
50
+ onPointerDown: handlePointerDown,
51
+ ...props,
52
+ children: [
53
+ loading && loaderPosition === "prefix" ? spinner : prefix,
54
+ children,
55
+ loading && loaderPosition === "suffix" ? spinner : suffix
56
+ ]
57
+ })
58
+ });
59
+ }
60
+ const INPUT_FIELD_NAME = "InputField";
61
+ function InputField({ __scopeInput, ...props }) {
62
+ /**
63
+ * Context values from parent Input component
64
+ */
65
+ const { disabled, inputRef, readOnly } = useInputContext(INPUT_FIELD_NAME, __scopeInput);
66
+ return /* @__PURE__ */ jsx("input", {
67
+ ref: useComposedRefs(inputRef),
68
+ disabled,
69
+ readOnly,
70
+ type: "text",
71
+ ...props
72
+ });
73
+ }
74
+ //#endregion
75
+ export { InputField as Field, InputField, Input, Input as Root, createInputScope };