@react-md/core 1.0.0-next.16 → 1.0.0-next.18

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 (665) hide show
  1. package/dist/_box-shadows.scss +76 -0
  2. package/dist/_colors.scss +279 -277
  3. package/dist/_core.scss +107 -16
  4. package/dist/_object-fit.scss +86 -0
  5. package/dist/_utils.scss +246 -72
  6. package/dist/app-bar/AppBar.d.ts +1 -90
  7. package/dist/app-bar/AppBar.js +1 -40
  8. package/dist/app-bar/AppBar.js.map +1 -1
  9. package/dist/app-bar/AppBarTitle.d.ts +1 -27
  10. package/dist/app-bar/AppBarTitle.js +1 -15
  11. package/dist/app-bar/AppBarTitle.js.map +1 -1
  12. package/dist/app-bar/_app-bar.scss +156 -25
  13. package/dist/app-bar/styles.d.ts +117 -0
  14. package/dist/app-bar/styles.js +55 -0
  15. package/dist/app-bar/styles.js.map +1 -0
  16. package/dist/autocomplete/Autocomplete.d.ts +8 -79
  17. package/dist/autocomplete/Autocomplete.js +112 -83
  18. package/dist/autocomplete/Autocomplete.js.map +1 -1
  19. package/dist/autocomplete/AutocompleteChip.d.ts +8 -0
  20. package/dist/autocomplete/AutocompleteChip.js +34 -0
  21. package/dist/autocomplete/AutocompleteChip.js.map +1 -0
  22. package/dist/autocomplete/AutocompleteCircularProgress.d.ts +5 -11
  23. package/dist/autocomplete/AutocompleteCircularProgress.js +4 -0
  24. package/dist/autocomplete/AutocompleteCircularProgress.js.map +1 -1
  25. package/dist/autocomplete/AutocompleteClearButton.d.ts +9 -0
  26. package/dist/autocomplete/AutocompleteClearButton.js +29 -0
  27. package/dist/autocomplete/AutocompleteClearButton.js.map +1 -0
  28. package/dist/autocomplete/AutocompleteDropdownButton.d.ts +4 -26
  29. package/dist/autocomplete/AutocompleteDropdownButton.js +5 -1
  30. package/dist/autocomplete/AutocompleteDropdownButton.js.map +1 -1
  31. package/dist/autocomplete/AutocompleteListboxChildren.d.ts +22 -0
  32. package/dist/autocomplete/AutocompleteListboxChildren.js +37 -0
  33. package/dist/autocomplete/AutocompleteListboxChildren.js.map +1 -0
  34. package/dist/autocomplete/_autocomplete.scss +362 -34
  35. package/dist/autocomplete/autocompleteStyles.d.ts +22 -0
  36. package/dist/autocomplete/autocompleteStyles.js +17 -8
  37. package/dist/autocomplete/autocompleteStyles.js.map +1 -1
  38. package/dist/autocomplete/defaults.d.ts +9 -9
  39. package/dist/autocomplete/defaults.js +13 -13
  40. package/dist/autocomplete/defaults.js.map +1 -1
  41. package/dist/autocomplete/types.d.ts +554 -56
  42. package/dist/autocomplete/types.js.map +1 -1
  43. package/dist/autocomplete/useAutocomplete.d.ts +22 -0
  44. package/dist/autocomplete/useAutocomplete.js +281 -0
  45. package/dist/autocomplete/useAutocomplete.js.map +1 -0
  46. package/dist/autocomplete/utils.d.ts +81 -0
  47. package/dist/autocomplete/utils.js +108 -0
  48. package/dist/autocomplete/utils.js.map +1 -0
  49. package/dist/avatar/_avatar.scss +93 -2
  50. package/dist/badge/Badge.d.ts +1 -20
  51. package/dist/badge/Badge.js +1 -14
  52. package/dist/badge/Badge.js.map +1 -1
  53. package/dist/badge/_badge.scss +90 -3
  54. package/dist/badge/styles.d.ts +26 -0
  55. package/dist/badge/styles.js +18 -0
  56. package/dist/badge/styles.js.map +1 -0
  57. package/dist/box/Box.js +2 -1
  58. package/dist/box/Box.js.map +1 -1
  59. package/dist/box/_box.scss +130 -17
  60. package/dist/box/styles.d.ts +6 -0
  61. package/dist/box/styles.js +2 -1
  62. package/dist/box/styles.js.map +1 -1
  63. package/dist/button/AsyncButton.d.ts +1 -1
  64. package/dist/button/AsyncButton.js.map +1 -1
  65. package/dist/button/Button.d.ts +2 -1
  66. package/dist/button/Button.js +2 -1
  67. package/dist/button/Button.js.map +1 -1
  68. package/dist/button/_button.scss +157 -25
  69. package/dist/card/Card.d.ts +16 -0
  70. package/dist/card/Card.js +11 -3
  71. package/dist/card/Card.js.map +1 -1
  72. package/dist/card/ClickableCard.d.ts +2 -1
  73. package/dist/card/ClickableCard.js +5 -2
  74. package/dist/card/ClickableCard.js.map +1 -1
  75. package/dist/card/_card.scss +90 -19
  76. package/dist/card/styles.d.ts +0 -7
  77. package/dist/card/styles.js +2 -3
  78. package/dist/card/styles.js.map +1 -1
  79. package/dist/chip/Chip.d.ts +2 -1
  80. package/dist/chip/Chip.js +2 -1
  81. package/dist/chip/Chip.js.map +1 -1
  82. package/dist/chip/_chip.scss +45 -22
  83. package/dist/chip/styles.d.ts +12 -10
  84. package/dist/chip/styles.js.map +1 -1
  85. package/dist/cssUtils.js.map +1 -1
  86. package/dist/delegateEvent.d.ts +2 -2
  87. package/dist/delegateEvent.js.map +1 -1
  88. package/dist/dialog/Dialog.d.ts +8 -21
  89. package/dist/dialog/Dialog.js +27 -27
  90. package/dist/dialog/Dialog.js.map +1 -1
  91. package/dist/dialog/FixedDialog.d.ts +1 -3
  92. package/dist/dialog/FixedDialog.js +0 -8
  93. package/dist/dialog/FixedDialog.js.map +1 -1
  94. package/dist/dialog/_dialog.scss +67 -13
  95. package/dist/dialog/styles.d.ts +56 -0
  96. package/dist/dialog/styles.js +29 -2
  97. package/dist/dialog/styles.js.map +1 -1
  98. package/dist/divider/Divider.d.ts +0 -11
  99. package/dist/divider/Divider.js.map +1 -1
  100. package/dist/divider/_divider.scss +7 -1
  101. package/dist/divider/styles.d.ts +11 -0
  102. package/dist/divider/styles.js.map +1 -1
  103. package/dist/draggable/useDraggable.d.ts +6 -6
  104. package/dist/draggable/useDraggable.js.map +1 -1
  105. package/dist/draggable/utils.d.ts +3 -3
  106. package/dist/draggable/utils.js.map +1 -1
  107. package/dist/expansion-panel/ExpansionPanel.d.ts +1 -1
  108. package/dist/expansion-panel/ExpansionPanel.js.map +1 -1
  109. package/dist/expansion-panel/_expansion-panel.scss +5 -1
  110. package/dist/expansion-panel/useExpansionPanels.js +12 -24
  111. package/dist/expansion-panel/useExpansionPanels.js.map +1 -1
  112. package/dist/{form → files}/FileInput.d.ts +3 -6
  113. package/dist/{form → files}/FileInput.js +3 -6
  114. package/dist/files/FileInput.js.map +1 -0
  115. package/dist/files/_files.scss +22 -0
  116. package/dist/files/styles.d.ts +5 -0
  117. package/dist/files/styles.js +7 -0
  118. package/dist/files/styles.js.map +1 -0
  119. package/dist/{form → files}/useFileUpload.d.ts +7 -9
  120. package/dist/{form → files}/useFileUpload.js +5 -7
  121. package/dist/files/useFileUpload.js.map +1 -0
  122. package/dist/files/utils.d.ts +169 -0
  123. package/dist/files/utils.js +114 -0
  124. package/dist/files/utils.js.map +1 -0
  125. package/dist/{form/fileUtils.d.ts → files/validation.d.ts} +11 -176
  126. package/dist/{form/fileUtils.js → files/validation.js} +10 -135
  127. package/dist/files/validation.js.map +1 -0
  128. package/dist/focus/useFocusContainer.d.ts +2 -2
  129. package/dist/focus/useFocusContainer.js.map +1 -1
  130. package/dist/focus/utils.js.map +1 -1
  131. package/dist/form/FormMessage.js.map +1 -1
  132. package/dist/form/FormMessageContainer.js +4 -2
  133. package/dist/form/FormMessageContainer.js.map +1 -1
  134. package/dist/form/InputToggle.d.ts +2 -1
  135. package/dist/form/InputToggle.js +2 -1
  136. package/dist/form/InputToggle.js.map +1 -1
  137. package/dist/form/InputToggleIcon.js.map +1 -1
  138. package/dist/form/Label.js +2 -2
  139. package/dist/form/Label.js.map +1 -1
  140. package/dist/form/Listbox.d.ts +24 -0
  141. package/dist/form/Listbox.js +46 -0
  142. package/dist/form/Listbox.js.map +1 -0
  143. package/dist/form/ListboxProvider.d.ts +21 -0
  144. package/dist/form/{useListboxProvider.js → ListboxProvider.js} +1 -1
  145. package/dist/form/ListboxProvider.js.map +1 -0
  146. package/dist/form/MenuItemTextField.js +1 -2
  147. package/dist/form/MenuItemTextField.js.map +1 -1
  148. package/dist/form/NativeSelect.js +7 -4
  149. package/dist/form/NativeSelect.js.map +1 -1
  150. package/dist/form/Option.d.ts +49 -10
  151. package/dist/form/Option.js +11 -9
  152. package/dist/form/Option.js.map +1 -1
  153. package/dist/form/Password.js.map +1 -1
  154. package/dist/form/Select.d.ts +2 -2
  155. package/dist/form/Select.js +81 -85
  156. package/dist/form/Select.js.map +1 -1
  157. package/dist/form/SelectedOption.js +2 -1
  158. package/dist/form/SelectedOption.js.map +1 -1
  159. package/dist/form/Slider.d.ts +4 -4
  160. package/dist/form/Slider.js +6 -2
  161. package/dist/form/Slider.js.map +1 -1
  162. package/dist/form/SliderThumb.d.ts +3 -3
  163. package/dist/form/SliderThumb.js.map +1 -1
  164. package/dist/form/SliderValueMarks.d.ts +2 -2
  165. package/dist/form/SliderValueMarks.js.map +1 -1
  166. package/dist/form/SliderValueTooltip.js.map +1 -1
  167. package/dist/form/TextArea.js +1 -2
  168. package/dist/form/TextArea.js.map +1 -1
  169. package/dist/form/TextField.js +1 -2
  170. package/dist/form/TextField.js.map +1 -1
  171. package/dist/form/TextFieldContainer.js +1 -2
  172. package/dist/form/TextFieldContainer.js.map +1 -1
  173. package/dist/form/_form.scss +193 -124
  174. package/dist/form/formMessageContainerStyles.d.ts +10 -0
  175. package/dist/form/formMessageContainerStyles.js +11 -0
  176. package/dist/form/formMessageContainerStyles.js.map +1 -0
  177. package/dist/form/inputToggleStyles.js.map +1 -1
  178. package/dist/form/optionStyles.d.ts +1 -0
  179. package/dist/form/optionStyles.js +2 -2
  180. package/dist/form/optionStyles.js.map +1 -1
  181. package/dist/form/selectUtils.js.map +1 -1
  182. package/dist/form/sliderUtils.d.ts +1 -1
  183. package/dist/form/sliderUtils.js.map +1 -1
  184. package/dist/form/textFieldContainerStyles.d.ts +0 -2
  185. package/dist/form/textFieldContainerStyles.js +1 -2
  186. package/dist/form/textFieldContainerStyles.js.map +1 -1
  187. package/dist/form/types.d.ts +3 -10
  188. package/dist/form/types.js.map +1 -1
  189. package/dist/form/useCheckboxGroup.d.ts +17 -17
  190. package/dist/form/useCheckboxGroup.js +9 -17
  191. package/dist/form/useCheckboxGroup.js.map +1 -1
  192. package/dist/form/useCombobox.d.ts +56 -21
  193. package/dist/form/useCombobox.js +19 -4
  194. package/dist/form/useCombobox.js.map +1 -1
  195. package/dist/form/useEditableCombobox.d.ts +24 -4
  196. package/dist/form/useEditableCombobox.js +5 -0
  197. package/dist/form/useEditableCombobox.js.map +1 -1
  198. package/dist/form/useNumberField.js.map +1 -1
  199. package/dist/form/useRadioGroup.d.ts +6 -6
  200. package/dist/form/useRadioGroup.js.map +1 -1
  201. package/dist/form/useResizingTextArea.js.map +1 -1
  202. package/dist/form/useSelectCombobox.d.ts +3 -4
  203. package/dist/form/useSelectCombobox.js.map +1 -1
  204. package/dist/form/useTextField.d.ts +1 -1
  205. package/dist/form/useTextField.js.map +1 -1
  206. package/dist/form/useTextFieldContainerAddons.js.map +1 -1
  207. package/dist/hoverMode/useHoverMode.d.ts +3 -3
  208. package/dist/hoverMode/useHoverMode.js.map +1 -1
  209. package/dist/hoverMode/useHoverModeProvider.d.ts +4 -4
  210. package/dist/hoverMode/useHoverModeProvider.js.map +1 -1
  211. package/dist/icon/FontIcon.d.ts +4 -2
  212. package/dist/icon/FontIcon.js.map +1 -1
  213. package/dist/icon/TextIconSpacing.d.ts +3 -1
  214. package/dist/icon/TextIconSpacing.js.map +1 -1
  215. package/dist/icon/_icon.scss +151 -2
  216. package/dist/icon/iconConfig.d.ts +10 -0
  217. package/dist/icon/iconConfig.js +7 -0
  218. package/dist/icon/iconConfig.js.map +1 -1
  219. package/dist/icon/materialConfig.js.map +1 -1
  220. package/dist/icon/styles.js.map +1 -1
  221. package/dist/interaction/UserInteractionModeProvider.d.ts +5 -5
  222. package/dist/interaction/UserInteractionModeProvider.js +12 -8
  223. package/dist/interaction/UserInteractionModeProvider.js.map +1 -1
  224. package/dist/interaction/types.d.ts +20 -2
  225. package/dist/interaction/types.js.map +1 -1
  226. package/dist/interaction/useElementInteraction.d.ts +7 -1
  227. package/dist/interaction/useElementInteraction.js +1 -2
  228. package/dist/interaction/useElementInteraction.js.map +1 -1
  229. package/dist/interaction/utils.d.ts +2 -2
  230. package/dist/interaction/utils.js +2 -2
  231. package/dist/interaction/utils.js.map +1 -1
  232. package/dist/layout/LayoutWindowSplitter.js.map +1 -1
  233. package/dist/layout/_layout.scss +23 -10
  234. package/dist/layout/useExpandableLayout.d.ts +3 -3
  235. package/dist/layout/useExpandableLayout.js.map +1 -1
  236. package/dist/layout/useLayoutAppBarHeight.d.ts +2 -3
  237. package/dist/layout/useLayoutAppBarHeight.js.map +1 -1
  238. package/dist/layout/useTemporaryLayout.d.ts +2 -2
  239. package/dist/layout/useTemporaryLayout.js.map +1 -1
  240. package/dist/link/SkipToMainContent.js.map +1 -1
  241. package/dist/list/ListItem.d.ts +2 -1
  242. package/dist/list/ListItem.js +2 -1
  243. package/dist/list/ListItem.js.map +1 -1
  244. package/dist/list/ListItemChildren.js.map +1 -1
  245. package/dist/list/ListItemLink.d.ts +2 -1
  246. package/dist/list/ListItemLink.js +2 -1
  247. package/dist/list/ListItemLink.js.map +1 -1
  248. package/dist/list/_list.scss +6 -5
  249. package/dist/media-queries/_media-queries.scss +12 -0
  250. package/dist/media-queries/appSize.js.map +1 -1
  251. package/dist/media-queries/useMediaQuery.js +3 -1
  252. package/dist/media-queries/useMediaQuery.js.map +1 -1
  253. package/dist/menu/DropdownMenu.js.map +1 -1
  254. package/dist/menu/Menu.d.ts +8 -3
  255. package/dist/menu/Menu.js +2 -1
  256. package/dist/menu/Menu.js.map +1 -1
  257. package/dist/menu/MenuItemButton.js +6 -2
  258. package/dist/menu/MenuItemButton.js.map +1 -1
  259. package/dist/menu/useContextMenu.d.ts +3 -3
  260. package/dist/menu/useContextMenu.js.map +1 -1
  261. package/dist/movement/types.d.ts +5 -5
  262. package/dist/movement/types.js.map +1 -1
  263. package/dist/navigation/CollapsibleNavGroup.d.ts +5 -3
  264. package/dist/navigation/CollapsibleNavGroup.js +3 -4
  265. package/dist/navigation/CollapsibleNavGroup.js.map +1 -1
  266. package/dist/navigation/DefaultNavigationRenderer.d.ts +1 -2
  267. package/dist/navigation/DefaultNavigationRenderer.js +6 -2
  268. package/dist/navigation/DefaultNavigationRenderer.js.map +1 -1
  269. package/dist/navigation/NavItemButton.d.ts +1 -1
  270. package/dist/navigation/NavItemButton.js +1 -0
  271. package/dist/navigation/NavItemButton.js.map +1 -1
  272. package/dist/navigation/NavItemLink.d.ts +3 -2
  273. package/dist/navigation/NavItemLink.js +6 -2
  274. package/dist/navigation/NavItemLink.js.map +1 -1
  275. package/dist/navigation/NavSubheader.d.ts +2 -3
  276. package/dist/navigation/NavSubheader.js.map +1 -1
  277. package/dist/navigation/Navigation.d.ts +1 -1
  278. package/dist/navigation/Navigation.js.map +1 -1
  279. package/dist/navigation/_navigation.scss +6 -5
  280. package/dist/navigation/types.d.ts +54 -6
  281. package/dist/navigation/types.js.map +1 -1
  282. package/dist/navigation/useActiveHeadingId.d.ts +1 -1
  283. package/dist/navigation/useActiveHeadingId.js.map +1 -1
  284. package/dist/navigation/useNavigationExpansion.d.ts +104 -0
  285. package/dist/navigation/useNavigationExpansion.js +77 -0
  286. package/dist/navigation/useNavigationExpansion.js.map +1 -0
  287. package/dist/navigation/utils.d.ts +13 -0
  288. package/dist/navigation/utils.js +36 -0
  289. package/dist/navigation/utils.js.map +1 -0
  290. package/dist/objectFit.d.ts +69 -0
  291. package/dist/objectFit.js +52 -0
  292. package/dist/objectFit.js.map +1 -0
  293. package/dist/overlay/_overlay.scss +2 -1
  294. package/dist/positioning/useFixedPositioning.d.ts +17 -4
  295. package/dist/positioning/useFixedPositioning.js +10 -5
  296. package/dist/positioning/useFixedPositioning.js.map +1 -1
  297. package/dist/positioning/utils.js.map +1 -1
  298. package/dist/progress/LinearProgress.js.map +1 -1
  299. package/dist/progress/_progress.scss +20 -14
  300. package/dist/responsive-item/ResponsiveItem.d.ts +64 -0
  301. package/dist/responsive-item/ResponsiveItem.js +68 -0
  302. package/dist/responsive-item/ResponsiveItem.js.map +1 -0
  303. package/dist/responsive-item/ResponsiveItemOverlay.d.ts +1 -19
  304. package/dist/responsive-item/ResponsiveItemOverlay.js +1 -12
  305. package/dist/responsive-item/ResponsiveItemOverlay.js.map +1 -1
  306. package/dist/responsive-item/_responsive-item.scss +110 -133
  307. package/dist/responsive-item/responsiveItemOverlayStyles.d.ts +19 -0
  308. package/dist/responsive-item/responsiveItemOverlayStyles.js +14 -0
  309. package/dist/responsive-item/responsiveItemOverlayStyles.js.map +1 -0
  310. package/dist/responsive-item/responsiveItemStyles.d.ts +52 -0
  311. package/dist/responsive-item/responsiveItemStyles.js +15 -0
  312. package/dist/responsive-item/responsiveItemStyles.js.map +1 -0
  313. package/dist/scroll/useScrollLock.d.ts +5 -0
  314. package/dist/scroll/useScrollLock.js.map +1 -1
  315. package/dist/searching/utils.d.ts +2 -2
  316. package/dist/searching/utils.js.map +1 -1
  317. package/dist/segmented-button/SegmentedButton.d.ts +2 -1
  318. package/dist/segmented-button/SegmentedButton.js +2 -1
  319. package/dist/segmented-button/SegmentedButton.js.map +1 -1
  320. package/dist/segmented-button/_segmented-button.scss +6 -6
  321. package/dist/sheet/_sheet.scss +18 -6
  322. package/dist/snackbar/ToastManager.js +15 -5
  323. package/dist/snackbar/ToastManager.js.map +1 -1
  324. package/dist/snackbar/_snackbar.scss +30 -17
  325. package/dist/snackbar/useCurrentToastActions.d.ts +5 -5
  326. package/dist/snackbar/useCurrentToastActions.js.map +1 -1
  327. package/dist/table/_table.scss +15 -3
  328. package/dist/table/tableCellStyles.d.ts +7 -3
  329. package/dist/table/tableCellStyles.js +2 -2
  330. package/dist/table/tableCellStyles.js.map +1 -1
  331. package/dist/tabs/Tab.d.ts +2 -1
  332. package/dist/tabs/Tab.js +2 -1
  333. package/dist/tabs/Tab.js.map +1 -1
  334. package/dist/tabs/TabList.d.ts +2 -2
  335. package/dist/tabs/TabList.js.map +1 -1
  336. package/dist/tabs/TabListScrollButton.d.ts +1 -1
  337. package/dist/tabs/TabListScrollButton.js +1 -1
  338. package/dist/tabs/TabListScrollButton.js.map +1 -1
  339. package/dist/tabs/_tabs.scss +30 -9
  340. package/dist/tabs/getTabListScrollToOptions.d.ts +18 -0
  341. package/dist/tabs/getTabListScrollToOptions.js +19 -0
  342. package/dist/tabs/getTabListScrollToOptions.js.map +1 -0
  343. package/dist/tabs/tabStyles.d.ts +3 -0
  344. package/dist/tabs/tabStyles.js.map +1 -1
  345. package/dist/tabs/useTabList.d.ts +1 -8
  346. package/dist/tabs/useTabList.js +1 -0
  347. package/dist/tabs/useTabList.js.map +1 -1
  348. package/dist/tabs/useTabs.d.ts +6 -6
  349. package/dist/tabs/useTabs.js.map +1 -1
  350. package/dist/tabs/utils.d.ts +0 -18
  351. package/dist/tabs/utils.js +0 -15
  352. package/dist/tabs/utils.js.map +1 -1
  353. package/dist/test-utils/ResizeObserver.d.ts +11 -12
  354. package/dist/test-utils/ResizeObserver.js +11 -12
  355. package/dist/test-utils/ResizeObserver.js.map +1 -1
  356. package/dist/test-utils/matchMedia.d.ts +3 -3
  357. package/dist/test-utils/matchMedia.js +6 -6
  358. package/dist/test-utils/matchMedia.js.map +1 -1
  359. package/dist/test-utils/polyfills/TextDecoder.js +0 -1
  360. package/dist/test-utils/polyfills/TextDecoder.js.map +1 -1
  361. package/dist/test-utils/timers.d.ts +9 -5
  362. package/dist/test-utils/timers.js +5 -5
  363. package/dist/test-utils/timers.js.map +1 -1
  364. package/dist/theme/LocalStorageColorSchemeProvider.d.ts +1 -1
  365. package/dist/theme/LocalStorageColorSchemeProvider.js +2 -1
  366. package/dist/theme/LocalStorageColorSchemeProvider.js.map +1 -1
  367. package/dist/theme/ThemeProvider.js +3 -1
  368. package/dist/theme/ThemeProvider.js.map +1 -1
  369. package/dist/theme/_a11y.scss +86 -13
  370. package/dist/theme/_colors.scss +279 -277
  371. package/dist/theme/_theme.scss +308 -37
  372. package/dist/theme/isColorScheme.d.ts +16 -0
  373. package/dist/theme/isColorScheme.js +19 -0
  374. package/dist/theme/isColorScheme.js.map +1 -0
  375. package/dist/theme/types.d.ts +53 -1
  376. package/dist/theme/types.js +1 -23
  377. package/dist/theme/types.js.map +1 -1
  378. package/dist/theme/useCSSVariables.d.ts +2 -19
  379. package/dist/theme/useCSSVariables.js.map +1 -1
  380. package/dist/theme/useColorScheme.d.ts +1 -35
  381. package/dist/theme/useColorScheme.js.map +1 -1
  382. package/dist/theme/useColorSchemeMetaTag.d.ts +1 -1
  383. package/dist/theme/useColorSchemeMetaTag.js.map +1 -1
  384. package/dist/theme/useColorSchemeProvider.d.ts +1 -1
  385. package/dist/theme/useColorSchemeProvider.js +1 -1
  386. package/dist/theme/useColorSchemeProvider.js.map +1 -1
  387. package/dist/theme/{usePrefersColorScheme.js → usePrefersDarkScheme.js} +1 -1
  388. package/dist/theme/usePrefersDarkScheme.js.map +1 -0
  389. package/dist/theme/utils.js.map +1 -1
  390. package/dist/tooltip/useTooltip.d.ts +14 -9
  391. package/dist/tooltip/useTooltip.js +2 -1
  392. package/dist/tooltip/useTooltip.js.map +1 -1
  393. package/dist/transition/_transition.scss +16 -9
  394. package/dist/transition/skeletonPlaceholderUtils.js.map +1 -1
  395. package/dist/transition/types.d.ts +1 -1
  396. package/dist/transition/types.js.map +1 -1
  397. package/dist/transition/useCarousel.d.ts +3 -3
  398. package/dist/transition/useCarousel.js.map +1 -1
  399. package/dist/transition/useCollapseTransition.js.map +1 -1
  400. package/dist/transition/useTransition.js +1 -0
  401. package/dist/transition/useTransition.js.map +1 -1
  402. package/dist/transition/utils.js.map +1 -1
  403. package/dist/tree/TreeItem.d.ts +2 -1
  404. package/dist/tree/TreeItem.js +4 -3
  405. package/dist/tree/TreeItem.js.map +1 -1
  406. package/dist/tree/TreeItemExpander.js.map +1 -1
  407. package/dist/tree/_tree.scss +8 -6
  408. package/dist/tree/useTreeExpansion.d.ts +1 -1
  409. package/dist/tree/useTreeExpansion.js +6 -18
  410. package/dist/tree/useTreeExpansion.js.map +1 -1
  411. package/dist/tree/useTreeSelection.d.ts +1 -1
  412. package/dist/tree/useTreeSelection.js +7 -25
  413. package/dist/tree/useTreeSelection.js.map +1 -1
  414. package/dist/tree/utils.d.ts +1 -1
  415. package/dist/tree/utils.js.map +1 -1
  416. package/dist/types.d.ts +12 -4
  417. package/dist/types.js.map +1 -1
  418. package/dist/typography/WritingDirectionProvider.d.ts +1 -1
  419. package/dist/typography/WritingDirectionProvider.js.map +1 -1
  420. package/dist/typography/_typography.scss +94 -37
  421. package/dist/typography/typographyStyles.js.map +1 -1
  422. package/dist/useDebouncedFunction.d.ts +1 -5
  423. package/dist/useDebouncedFunction.js +3 -1
  424. package/dist/useDebouncedFunction.js.map +1 -1
  425. package/dist/useDropzone.d.ts +4 -4
  426. package/dist/useDropzone.js.map +1 -1
  427. package/dist/useEnsuredId.js.map +1 -1
  428. package/dist/useIntersectionObserver.d.ts +5 -5
  429. package/dist/useIntersectionObserver.js.map +1 -1
  430. package/dist/useLocalStorage.d.ts +3 -3
  431. package/dist/useLocalStorage.js +1 -1
  432. package/dist/useLocalStorage.js.map +1 -1
  433. package/dist/useMutationObserver.d.ts +1 -1
  434. package/dist/useMutationObserver.js.map +1 -1
  435. package/dist/useOrientation.js +3 -1
  436. package/dist/useOrientation.js.map +1 -1
  437. package/dist/usePageInactive.d.ts +2 -2
  438. package/dist/usePageInactive.js.map +1 -1
  439. package/dist/useReadonlySet.d.ts +76 -0
  440. package/dist/useReadonlySet.js +72 -0
  441. package/dist/useReadonlySet.js.map +1 -0
  442. package/dist/useResizeListener.d.ts +1 -1
  443. package/dist/useResizeListener.js.map +1 -1
  444. package/dist/useResizeObserver.d.ts +19 -0
  445. package/dist/useResizeObserver.js +19 -0
  446. package/dist/useResizeObserver.js.map +1 -1
  447. package/dist/useThrottledFunction.d.ts +1 -5
  448. package/dist/useThrottledFunction.js +3 -1
  449. package/dist/useThrottledFunction.js.map +1 -1
  450. package/dist/useToggle.d.ts +3 -3
  451. package/dist/useToggle.js.map +1 -1
  452. package/dist/utils/RenderRecursively.d.ts +2 -2
  453. package/dist/utils/RenderRecursively.js.map +1 -1
  454. package/dist/utils/alphaNumericSort.d.ts +5 -5
  455. package/dist/utils/alphaNumericSort.js.map +1 -1
  456. package/dist/utils/bem.d.ts +1 -1
  457. package/dist/utils/bem.js +1 -1
  458. package/dist/utils/bem.js.map +1 -1
  459. package/dist/utils/debounce.d.ts +5 -0
  460. package/dist/utils/debounce.js +17 -0
  461. package/dist/utils/debounce.js.map +1 -0
  462. package/dist/utils/nearest.js.map +1 -1
  463. package/dist/utils/parseCssLengthUnit.js.map +1 -1
  464. package/dist/utils/throttle.d.ts +5 -0
  465. package/dist/utils/throttle.js +30 -0
  466. package/dist/utils/throttle.js.map +1 -0
  467. package/dist/utils/wait.js +3 -1
  468. package/dist/utils/wait.js.map +1 -1
  469. package/dist/window-splitter/WindowSplitter.d.ts +37 -15
  470. package/dist/window-splitter/WindowSplitter.js +38 -17
  471. package/dist/window-splitter/WindowSplitter.js.map +1 -1
  472. package/dist/window-splitter/_window-splitter.scss +32 -14
  473. package/dist/window-splitter/styles.d.ts +14 -0
  474. package/dist/window-splitter/styles.js +18 -0
  475. package/dist/window-splitter/styles.js.map +1 -0
  476. package/package.json +25 -24
  477. package/src/app-bar/AppBar.tsx +1 -170
  478. package/src/app-bar/AppBarTitle.tsx +1 -44
  479. package/src/app-bar/styles.ts +206 -0
  480. package/src/autocomplete/Autocomplete.tsx +194 -211
  481. package/src/autocomplete/AutocompleteChip.tsx +48 -0
  482. package/src/autocomplete/AutocompleteCircularProgress.tsx +6 -17
  483. package/src/autocomplete/AutocompleteClearButton.tsx +44 -0
  484. package/src/autocomplete/AutocompleteDropdownButton.tsx +16 -37
  485. package/src/autocomplete/AutocompleteListboxChildren.tsx +68 -0
  486. package/src/autocomplete/autocompleteStyles.ts +48 -9
  487. package/src/autocomplete/defaults.ts +26 -17
  488. package/src/autocomplete/types.ts +744 -61
  489. package/src/autocomplete/useAutocomplete.ts +428 -0
  490. package/src/autocomplete/utils.ts +211 -0
  491. package/src/badge/Badge.tsx +1 -39
  492. package/src/badge/styles.ts +45 -0
  493. package/src/box/Box.tsx +11 -9
  494. package/src/box/styles.ts +14 -5
  495. package/src/button/AsyncButton.tsx +1 -1
  496. package/src/button/Button.tsx +5 -1
  497. package/src/card/Card.tsx +35 -4
  498. package/src/card/ClickableCard.tsx +9 -2
  499. package/src/card/styles.ts +1 -10
  500. package/src/chip/Chip.tsx +6 -1
  501. package/src/chip/styles.ts +12 -10
  502. package/src/delegateEvent.ts +5 -5
  503. package/src/dialog/Dialog.tsx +48 -61
  504. package/src/dialog/FixedDialog.tsx +1 -11
  505. package/src/dialog/styles.ts +97 -0
  506. package/src/divider/Divider.tsx +0 -12
  507. package/src/divider/styles.ts +12 -0
  508. package/src/draggable/useDraggable.ts +17 -10
  509. package/src/draggable/utils.ts +3 -3
  510. package/src/expansion-panel/ExpansionPanel.tsx +1 -1
  511. package/src/expansion-panel/useExpansionPanels.ts +18 -27
  512. package/src/{form → files}/FileInput.tsx +7 -15
  513. package/src/files/styles.ts +10 -0
  514. package/src/{form → files}/useFileUpload.ts +30 -34
  515. package/src/files/utils.ts +234 -0
  516. package/src/{form/fileUtils.ts → files/validation.ts} +15 -244
  517. package/src/focus/useFocusContainer.ts +16 -8
  518. package/src/form/FormMessageContainer.tsx +2 -2
  519. package/src/form/InputToggle.tsx +5 -1
  520. package/src/form/Label.tsx +18 -18
  521. package/src/form/Listbox.tsx +87 -0
  522. package/src/form/ListboxProvider.ts +37 -0
  523. package/src/form/MenuItemTextField.tsx +1 -2
  524. package/src/form/NativeSelect.tsx +14 -10
  525. package/src/form/Option.tsx +74 -22
  526. package/src/form/Select.tsx +89 -85
  527. package/src/form/SelectedOption.tsx +2 -0
  528. package/src/form/Slider.tsx +14 -11
  529. package/src/form/SliderThumb.tsx +4 -4
  530. package/src/form/SliderValueMarks.tsx +4 -4
  531. package/src/form/TextArea.tsx +6 -8
  532. package/src/form/TextField.tsx +0 -2
  533. package/src/form/TextFieldContainer.tsx +9 -11
  534. package/src/form/formMessageContainerStyles.ts +22 -0
  535. package/src/form/optionStyles.ts +7 -2
  536. package/src/form/sliderUtils.ts +1 -1
  537. package/src/form/textFieldContainerStyles.ts +9 -14
  538. package/src/form/types.ts +3 -11
  539. package/src/form/useCheckboxGroup.ts +28 -36
  540. package/src/form/useCombobox.ts +86 -38
  541. package/src/form/useEditableCombobox.ts +43 -8
  542. package/src/form/useRadioGroup.ts +6 -6
  543. package/src/form/useSelectCombobox.ts +4 -4
  544. package/src/form/useTextField.ts +1 -1
  545. package/src/hoverMode/useHoverMode.ts +3 -3
  546. package/src/hoverMode/useHoverModeProvider.ts +4 -4
  547. package/src/icon/FontIcon.tsx +4 -2
  548. package/src/icon/TextIconSpacing.tsx +1 -1
  549. package/src/icon/iconConfig.tsx +12 -0
  550. package/src/interaction/UserInteractionModeProvider.tsx +12 -8
  551. package/src/interaction/types.ts +21 -2
  552. package/src/interaction/useElementInteraction.tsx +9 -2
  553. package/src/interaction/utils.ts +7 -7
  554. package/src/layout/useExpandableLayout.ts +3 -3
  555. package/src/layout/useLayoutAppBarHeight.ts +3 -4
  556. package/src/layout/useTemporaryLayout.ts +2 -2
  557. package/src/list/ListItem.tsx +5 -1
  558. package/src/list/ListItemLink.tsx +5 -1
  559. package/src/media-queries/useMediaQuery.ts +2 -1
  560. package/src/menu/Menu.tsx +11 -3
  561. package/src/menu/MenuItemButton.tsx +7 -1
  562. package/src/menu/useContextMenu.ts +3 -3
  563. package/src/movement/types.ts +5 -5
  564. package/src/navigation/CollapsibleNavGroup.tsx +16 -8
  565. package/src/navigation/DefaultNavigationRenderer.tsx +8 -6
  566. package/src/navigation/NavItemButton.tsx +2 -1
  567. package/src/navigation/NavItemLink.tsx +11 -3
  568. package/src/navigation/NavSubheader.tsx +1 -1
  569. package/src/navigation/Navigation.tsx +1 -1
  570. package/src/navigation/types.ts +60 -10
  571. package/src/navigation/useActiveHeadingId.ts +1 -1
  572. package/src/navigation/useNavigationExpansion.ts +170 -0
  573. package/src/navigation/utils.ts +47 -0
  574. package/src/objectFit.ts +88 -0
  575. package/src/positioning/useFixedPositioning.ts +34 -11
  576. package/src/responsive-item/ResponsiveItem.tsx +96 -0
  577. package/src/responsive-item/ResponsiveItemOverlay.tsx +6 -46
  578. package/src/responsive-item/responsiveItemOverlayStyles.ts +46 -0
  579. package/src/responsive-item/responsiveItemStyles.ts +81 -0
  580. package/src/scroll/useScrollLock.ts +6 -0
  581. package/src/searching/utils.ts +3 -3
  582. package/src/segmented-button/SegmentedButton.tsx +5 -1
  583. package/src/snackbar/ToastManager.tsx +16 -5
  584. package/src/snackbar/useCurrentToastActions.ts +5 -5
  585. package/src/table/tableCellStyles.ts +10 -6
  586. package/src/tabs/Tab.tsx +4 -1
  587. package/src/tabs/TabList.tsx +2 -2
  588. package/src/tabs/TabListScrollButton.tsx +4 -4
  589. package/src/tabs/getTabListScrollToOptions.ts +37 -0
  590. package/src/tabs/tabStyles.ts +4 -0
  591. package/src/tabs/useTabList.ts +2 -9
  592. package/src/tabs/useTabs.ts +6 -6
  593. package/src/tabs/utils.ts +0 -38
  594. package/src/test-utils/ResizeObserver.ts +11 -12
  595. package/src/test-utils/matchMedia.ts +7 -7
  596. package/src/test-utils/polyfills/TextDecoder.ts +0 -1
  597. package/src/test-utils/timers.ts +10 -7
  598. package/src/theme/LocalStorageColorSchemeProvider.tsx +4 -4
  599. package/src/theme/ThemeProvider.tsx +3 -3
  600. package/src/theme/isColorScheme.ts +22 -0
  601. package/src/theme/types.ts +67 -1
  602. package/src/theme/useCSSVariables.ts +7 -30
  603. package/src/theme/useColorScheme.ts +1 -40
  604. package/src/theme/useColorSchemeMetaTag.ts +1 -1
  605. package/src/theme/useColorSchemeProvider.ts +2 -2
  606. package/src/tooltip/useTooltip.ts +17 -9
  607. package/src/transition/types.ts +1 -1
  608. package/src/transition/useCarousel.ts +3 -3
  609. package/src/transition/useTransition.ts +1 -0
  610. package/src/tree/TreeItem.tsx +7 -1
  611. package/src/tree/TreeItemExpander.tsx +1 -1
  612. package/src/tree/useTreeExpansion.ts +7 -25
  613. package/src/tree/useTreeSelection.ts +8 -32
  614. package/src/tree/utils.ts +6 -2
  615. package/src/types.ts +20 -4
  616. package/src/typography/WritingDirectionProvider.tsx +1 -1
  617. package/src/useDebouncedFunction.ts +4 -9
  618. package/src/useDropzone.ts +4 -4
  619. package/src/useIntersectionObserver.ts +5 -5
  620. package/src/useLocalStorage.ts +6 -6
  621. package/src/useMutationObserver.ts +1 -1
  622. package/src/useOrientation.ts +3 -1
  623. package/src/usePageInactive.ts +2 -2
  624. package/src/useReadonlySet.ts +122 -0
  625. package/src/useResizeListener.ts +1 -1
  626. package/src/useResizeObserver.ts +19 -0
  627. package/src/useThrottledFunction.ts +6 -9
  628. package/src/useToggle.ts +3 -3
  629. package/src/utils/RenderRecursively.tsx +2 -2
  630. package/src/utils/alphaNumericSort.ts +5 -5
  631. package/src/utils/bem.ts +1 -1
  632. package/src/utils/debounce.ts +22 -0
  633. package/src/utils/throttle.ts +38 -0
  634. package/src/utils/wait.ts +5 -1
  635. package/src/window-splitter/WindowSplitter.tsx +38 -43
  636. package/src/window-splitter/styles.ts +42 -0
  637. package/dist/autocomplete/FilterAutocompleteOptions.d.ts +0 -8
  638. package/dist/autocomplete/FilterAutocompleteOptions.js +0 -57
  639. package/dist/autocomplete/FilterAutocompleteOptions.js.map +0 -1
  640. package/dist/dialog/DialogContainer.d.ts +0 -14
  641. package/dist/dialog/DialogContainer.js +0 -20
  642. package/dist/dialog/DialogContainer.js.map +0 -1
  643. package/dist/form/FileInput.js.map +0 -1
  644. package/dist/form/fileUtils.js.map +0 -1
  645. package/dist/form/useFileUpload.js.map +0 -1
  646. package/dist/form/useListboxProvider.d.ts +0 -31
  647. package/dist/form/useListboxProvider.js.map +0 -1
  648. package/dist/navigation/getHrefFromParents.d.ts +0 -5
  649. package/dist/navigation/getHrefFromParents.js +0 -13
  650. package/dist/navigation/getHrefFromParents.js.map +0 -1
  651. package/dist/responsive-item/ResponsiveItemContainer.d.ts +0 -115
  652. package/dist/responsive-item/ResponsiveItemContainer.js +0 -80
  653. package/dist/responsive-item/ResponsiveItemContainer.js.map +0 -1
  654. package/dist/responsive-item/styles.d.ts +0 -34
  655. package/dist/responsive-item/styles.js +0 -17
  656. package/dist/responsive-item/styles.js.map +0 -1
  657. package/dist/theme/usePrefersColorScheme.js.map +0 -1
  658. package/src/autocomplete/FilterAutocompleteOptions.tsx +0 -86
  659. package/src/dialog/DialogContainer.tsx +0 -28
  660. package/src/form/useListboxProvider.ts +0 -45
  661. package/src/navigation/getHrefFromParents.ts +0 -15
  662. package/src/responsive-item/ResponsiveItemContainer.tsx +0 -174
  663. package/src/responsive-item/styles.ts +0 -58
  664. /package/dist/theme/{usePrefersColorScheme.d.ts → usePrefersDarkScheme.d.ts} +0 -0
  665. /package/src/theme/{usePrefersColorScheme.ts → usePrefersDarkScheme.ts} +0 -0
@@ -1,11 +1,11 @@
1
1
  "use client";
2
- import { useRef } from "react";
2
+ import { useCallback, useRef } from "react";
3
3
  import { useKeyboardMovementProvider } from "../movement/useKeyboardMovementProvider.js";
4
4
  import { BELOW_CENTER_ANCHOR } from "../positioning/constants.js";
5
5
  import { TRANSITION_CONFIG } from "../transition/config.js";
6
6
  import { useEnsuredId } from "../useEnsuredId.js";
7
7
  import { useEnsuredRef } from "../useEnsuredRef.js";
8
- import { useToggle } from "../useToggle.js";
8
+ import { useEnsuredState } from "../useEnsuredState.js";
9
9
  import { tryToSubmitRelatedForm } from "./utils.js";
10
10
  const noop = ()=>{
11
11
  // do nothing
@@ -18,8 +18,22 @@ const noop = ()=>{
18
18
  /**
19
19
  * @since 6.0.0
20
20
  */ export function useCombobox(options) {
21
- const { form, popup = "listbox", onClick = noop, onFocus, onKeyDown, searchable, isNegativeOneAllowed, loopable, disabled, comboboxId: propComboboxId, comboboxRef: propComboboxRef, popupId: propPopupId, popupRef: propPopupRef, defaultVisible = false, onFocusChange = noop, extendKeyDown = noop, getFocusableElements = getNonDisabledOptions, getEnterDefaultFocusedIndex, getDefaultFocusedIndex } = options;
22
- const { toggled: visible, enable: show, disable: hide, setToggled: setVisible } = useToggle(defaultVisible);
21
+ const { form, popup = "listbox", onClick = noop, onFocus, onKeyDown, searchable, multiselect, isNegativeOneAllowed, loopable, disabled, visible: propVisible, setVisible: propSetVisible, defaultVisible = false, comboboxId: propComboboxId, comboboxRef: propComboboxRef, popupId: propPopupId, popupRef: propPopupRef, onFocusChange = noop, extendKeyDown = noop, getFocusableElements = getNonDisabledOptions, getEnterDefaultFocusedIndex, getDefaultFocusedIndex } = options;
22
+ const [visible, setVisible] = useEnsuredState({
23
+ value: propVisible,
24
+ setValue: propSetVisible,
25
+ defaultValue: defaultVisible
26
+ });
27
+ const show = useCallback(()=>{
28
+ setVisible(true);
29
+ }, [
30
+ setVisible
31
+ ]);
32
+ const hide = useCallback(()=>{
33
+ setVisible(false);
34
+ }, [
35
+ setVisible
36
+ ]);
23
37
  const popupId = useEnsuredId(propPopupId, "combobox-popup");
24
38
  const comboboxId = useEnsuredId(propComboboxId, "combobox");
25
39
  const [comboboxRef, comboboxRefCallback] = useEnsuredRef(propComboboxRef);
@@ -151,6 +165,7 @@ const noop = ()=>{
151
165
  };
152
166
  };
153
167
  const popupProps = {
168
+ "aria-multiselectable": multiselect || undefined,
154
169
  id: popupId,
155
170
  ref: popupRefCallback,
156
171
  role: popup
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/form/useCombobox.ts"],"sourcesContent":["\"use client\";\nimport {\n useRef,\n type FocusEventHandler,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n type InputHTMLAttributes,\n type KeyboardEventHandler,\n type MouseEventHandler,\n type Ref,\n type RefCallback,\n type RefObject,\n} from \"react\";\nimport { type MenuProps } from \"../menu/Menu.js\";\nimport { type MenuSheetConfigurableProps } from \"../menu/MenuSheet.js\";\nimport {\n type GetDefaultFocusedIndex,\n type GetFocusableElements,\n type KeyboardMovementExtensionData,\n type KeyboardMovementProviderImplementation,\n type KeyboardMovementProviderOptions,\n} from \"../movement/types.js\";\nimport { useKeyboardMovementProvider } from \"../movement/useKeyboardMovementProvider.js\";\nimport { BELOW_CENTER_ANCHOR } from \"../positioning/constants.js\";\nimport {\n type PositionAnchor,\n type PositionWidth,\n} from \"../positioning/types.js\";\nimport { TRANSITION_CONFIG } from \"../transition/config.js\";\nimport {\n type TransitionCallbacks,\n type TransitionEnterHandler,\n type TransitionExitHandler,\n} from \"../transition/types.js\";\nimport {\n type NonNullMutableRef,\n type UseStateInitializer,\n type UseStateSetter,\n} from \"../types.js\";\nimport { useEnsuredId } from \"../useEnsuredId.js\";\nimport { useEnsuredRef } from \"../useEnsuredRef.js\";\nimport { useToggle } from \"../useToggle.js\";\nimport { tryToSubmitRelatedForm } from \"./utils.js\";\n\nconst noop = (): void => {\n // do nothing\n};\n\n/**\n * @since 6.0.0\n */\nexport const getNonDisabledOptions = (\n container: HTMLElement\n): readonly HTMLElement[] => [\n ...container.querySelectorAll<HTMLLIElement>(\n '[role=\"option\"]:not([aria-disabled])'\n ),\n];\n\n/**\n * @since 6.0.0\n */\nexport type SupportedComboboxPopup = \"listbox\" | \"grid\" | \"dialog\";\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxKeyboardMovementData<\n E extends HTMLElement = HTMLInputElement,\n> extends KeyboardMovementExtensionData<E> {\n show(): void;\n hide(): void;\n visible: boolean;\n focusLast: NonNullMutableRef<boolean>;\n}\n\n/**\n * @since 6.0.0\n */\nexport type ExtendComboboxKeyDown<E extends HTMLElement = HTMLInputElement> = (\n movementData: ComboboxKeyboardMovementData<E>\n) => void;\n\n/**\n * @since 6.0.0\n */\nexport type ComboboxKeyboardMovementOptions<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n> = Pick<\n KeyboardMovementProviderOptions<ComboboxEl>,\n | \"onClick\"\n | \"onFocus\"\n | \"onKeyDown\"\n | \"disabled\"\n | \"loopable\"\n | \"searchable\"\n | \"onFocusChange\"\n | \"isNegativeOneAllowed\"\n>;\n\n/**\n * @since 6.0.0\n */\nexport interface BaseComboboxOptions<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends ComboboxKeyboardMovementOptions<ComboboxEl> {\n /**\n * This is the {@link InputHTMLAttributes.form} attribute and is used to\n * attempt submitting a form when the enter key is pressed.\n */\n form?: string;\n\n /**\n * @defaultValue `\"combobox-popup-\" + useId()`\n */\n popupId?: string;\n popupRef?: Ref<PopupEl>;\n\n /**\n * @defaultValue `\"combobox-\" + useId()`\n */\n comboboxId?: string;\n comboboxRef?: Ref<ComboboxEl>;\n\n /**\n * @defaultValue `\"listbox\"`\n */\n popup?: \"listbox\" | \"grid\" | \"dialog\";\n\n /**\n * @defaultValue `false`\n */\n defaultVisible?: UseStateInitializer<boolean>;\n\n extendKeyDown?: ExtendComboboxKeyDown<ComboboxEl>;\n\n /**\n * @defaultValue {@link getNonDisabledOptions}\n */\n getFocusableElements?: GetFocusableElements;\n\n getDefaultFocusedIndex?: GetDefaultFocusedIndex;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxOptions<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends BaseComboboxOptions<ComboboxEl, PopupEl> {\n getEnterDefaultFocusedIndex(options: {\n focusLast: boolean;\n focusables: readonly HTMLElement[];\n currentFocusIndex: number;\n }): number;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxWidgetProps<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n> {\n \"aria-controls\": string;\n \"aria-disabled\": true | undefined;\n \"aria-expanded\": boolean;\n \"aria-haspopup\": SupportedComboboxPopup;\n id: string;\n ref: RefCallback<ComboboxEl>;\n role: \"combobox\";\n onClick: MouseEventHandler<ComboboxEl>;\n onFocus: FocusEventHandler<ComboboxEl>;\n onKeyDown: KeyboardEventHandler<ComboboxEl>;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxWidgetPopupProps<\n PopupEl extends HTMLElement = HTMLElement,\n> {\n id: string;\n ref: RefCallback<PopupEl>;\n role: \"listbox\" | \"dialog\" | \"grid\";\n}\n\n/**\n * @since 6.0.0\n */\nexport type ComboboxTransitionCallbacks = Pick<\n TransitionCallbacks,\n \"onEntering\" | \"onEntered\" | \"onExiting\" | \"onExited\"\n>;\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxTransitionOptions extends ComboboxTransitionCallbacks {\n disableTransition?: boolean;\n}\n\n/**\n * @since 6.0.0\n */\nexport type ConfigurableComboboxMenuProps = Partial<\n Omit<MenuProps, \"visible\" | \"onRequestClose\" | keyof ComboboxWidgetPopupProps>\n>;\n\n/**\n * @since 6.0.0\n */\nexport interface ProvidedComboboxMenuProps<\n PopupEl extends HTMLElement = HTMLDivElement,\n> extends Required<ComboboxTransitionCallbacks>,\n ComboboxWidgetPopupProps<PopupEl> {\n visible: boolean;\n onRequestClose(): void;\n\n /** @defaultValue `\"min\"` */\n width: PositionWidth;\n\n /** @defaultValue `BELOW_CENTER_ANCHOR` */\n anchor: PositionAnchor;\n\n fixedTo: RefObject<HTMLElement>;\n\n sheetProps: MenuSheetConfigurableProps &\n Required<ComboboxTransitionCallbacks>;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxMenuProps<PopupEl extends HTMLElement = HTMLDivElement>\n extends Omit<ConfigurableComboboxMenuProps, keyof ProvidedComboboxMenuProps>,\n ProvidedComboboxMenuProps<PopupEl> {}\n\n/**\n * Since the combobox usually uses the `Menu` as a popup element, this is a\n * helper util to create the required props and merge any additional props\n * with reasonable defaults.\n */\nexport type ComboboxGetMenuProps<PopupEl extends HTMLElement = HTMLDivElement> =\n (props?: ConfigurableComboboxMenuProps) => ComboboxMenuProps<PopupEl>;\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxImplementation<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends KeyboardMovementProviderImplementation<ComboboxEl> {\n show(): void;\n hide(): void;\n visible: boolean;\n setVisible: UseStateSetter<boolean>;\n focusLast: NonNullMutableRef<boolean>;\n popupRef: RefObject<PopupEl>;\n popupProps: ComboboxWidgetPopupProps<PopupEl>;\n comboboxRef: RefObject<ComboboxEl>;\n comboboxProps: ComboboxWidgetProps<ComboboxEl>;\n\n getMenuProps: ComboboxGetMenuProps<PopupEl>;\n getTransitionCallbacks(\n options: ComboboxTransitionOptions\n ): Required<ComboboxTransitionCallbacks>;\n}\n\n/**\n * @since 6.0.0\n */\nexport function useCombobox<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n>(\n options: ComboboxOptions<ComboboxEl, PopupEl>\n): ComboboxImplementation<ComboboxEl, PopupEl> {\n const {\n form,\n popup = \"listbox\",\n onClick = noop,\n onFocus,\n onKeyDown,\n searchable,\n isNegativeOneAllowed,\n loopable,\n disabled,\n comboboxId: propComboboxId,\n comboboxRef: propComboboxRef,\n popupId: propPopupId,\n popupRef: propPopupRef,\n defaultVisible = false,\n onFocusChange = noop,\n extendKeyDown = noop,\n getFocusableElements = getNonDisabledOptions,\n getEnterDefaultFocusedIndex,\n getDefaultFocusedIndex,\n } = options;\n\n const {\n toggled: visible,\n enable: show,\n disable: hide,\n setToggled: setVisible,\n } = useToggle(defaultVisible);\n const popupId = useEnsuredId(propPopupId, \"combobox-popup\");\n const comboboxId = useEnsuredId(propComboboxId, \"combobox\");\n const [comboboxRef, comboboxRefCallback] = useEnsuredRef(propComboboxRef);\n const [popupRef, popupRefCallback] = useEnsuredRef(propPopupRef);\n const focusLast = useRef(false);\n const {\n movementProps,\n movementContext,\n currentFocusIndex,\n activeDescendantId,\n setActiveDescendantId,\n } = useKeyboardMovementProvider<ComboboxEl>({\n onFocus,\n onKeyDown,\n onClick(event) {\n onClick(event);\n if (disabled) {\n return;\n }\n\n show();\n },\n extendKeyDown(movementData) {\n extendKeyDown({\n ...movementData,\n show,\n hide,\n visible,\n focusLast,\n });\n const { event } = movementData;\n if (event.isPropagationStopped()) {\n return;\n }\n\n if (visible) {\n switch (event.key) {\n case \"Tab\":\n case \"Escape\":\n event.stopPropagation();\n hide();\n break;\n case \"Enter\":\n event.preventDefault();\n break;\n }\n\n // while visible, always use the default keyboard movement behavior\n return;\n }\n\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowDown\":\n event.preventDefault();\n event.stopPropagation();\n focusLast.current = event.key === \"ArrowUp\";\n show();\n break;\n case \"Enter\":\n tryToSubmitRelatedForm(event, form);\n break;\n }\n },\n disabled,\n loopable,\n searchable,\n onFocusChange,\n programmatic: true,\n includeDisabled: false,\n tabIndexBehavior: \"virtual\",\n getFocusableElements(container, programmatic) {\n const popup = popupRef.current;\n if (!popup) {\n return [];\n }\n\n return getFocusableElements(popup || container, programmatic);\n },\n isNegativeOneAllowed,\n getDefaultFocusedIndex,\n });\n const getTransitionCallbacks = (\n options: ComboboxTransitionOptions = {}\n ): Required<ComboboxTransitionCallbacks> => {\n const { onEntered, onEntering, onExiting, onExited, disableTransition } =\n options;\n\n const handleEntering =\n (callback: TransitionEnterHandler = noop, skipped: boolean) =>\n (appearing: boolean) => {\n callback(appearing);\n\n const popup = popupRef.current;\n if (!popup || skipped) {\n // Chrome does not trigger the scrollIntoView behavior correctly while\n // using a scale transition, so need to trigger this on the entered\n // flow to really make sure the item is in view.\n // An alternative would be to implement a custom scrollIntoView\n // behavior again like the previous versions of react-md, but this is\n // less lines of code\n const activeOption = document.getElementById(activeDescendantId);\n if (activeOption) {\n activeOption.scrollIntoView({ block: \"nearest\" });\n }\n return;\n }\n\n const focusables = getFocusableElements(popup, true);\n const index = getEnterDefaultFocusedIndex({\n focusLast: focusLast.current,\n focusables,\n currentFocusIndex: currentFocusIndex.current,\n });\n focusLast.current = false;\n currentFocusIndex.current = index;\n\n const option = focusables[index];\n if (!option) {\n return;\n }\n\n onFocusChange({\n index,\n element: option,\n });\n\n option.scrollIntoView({ block: \"nearest\" });\n setActiveDescendantId(option.id || \"\");\n };\n const handleExiting =\n (callback: TransitionExitHandler = noop, skipped: boolean) =>\n (): void => {\n callback();\n\n if (!skipped) {\n // since the menu is unmounted or set to hidden while not visible, need\n // to clear the aria-activedescendant and current focus index when\n // hiding\n currentFocusIndex.current = -1;\n setActiveDescendantId(\"\");\n }\n };\n\n const isTransitionCompleteSkipped =\n !disableTransition && !TRANSITION_CONFIG.disabled;\n\n return {\n onEntering: handleEntering(onEntering, false),\n onEntered: handleEntering(onEntered, isTransitionCompleteSkipped),\n onExiting: handleExiting(onExiting, false),\n onExited: handleExiting(onExited, isTransitionCompleteSkipped),\n };\n };\n\n const popupProps: ComboboxWidgetPopupProps<PopupEl> = {\n id: popupId,\n ref: popupRefCallback,\n role: popup,\n };\n\n return {\n show,\n hide,\n visible,\n setVisible,\n focusLast,\n popupRef,\n popupProps,\n comboboxRef,\n comboboxProps: {\n ...movementProps,\n \"aria-controls\": popupId,\n \"aria-disabled\": disabled || undefined,\n \"aria-expanded\": visible,\n \"aria-haspopup\": popup,\n id: comboboxId,\n ref: comboboxRefCallback,\n role: \"combobox\",\n },\n movementProps,\n movementContext,\n currentFocusIndex,\n activeDescendantId,\n setActiveDescendantId,\n getTransitionCallbacks,\n getMenuProps(props = {}) {\n const { sheetProps, disableTransition } = props;\n return {\n anchor: BELOW_CENTER_ANCHOR,\n width: \"min\",\n fixedTo: comboboxRef,\n ...props,\n ...popupProps,\n visible,\n onRequestClose: hide,\n ...getTransitionCallbacks(props),\n sheetProps: {\n ...sheetProps,\n ...getTransitionCallbacks({\n ...sheetProps,\n disableTransition:\n sheetProps?.disableTransition ?? disableTransition,\n }),\n },\n };\n },\n };\n}\n"],"names":["useRef","useKeyboardMovementProvider","BELOW_CENTER_ANCHOR","TRANSITION_CONFIG","useEnsuredId","useEnsuredRef","useToggle","tryToSubmitRelatedForm","noop","getNonDisabledOptions","container","querySelectorAll","useCombobox","options","form","popup","onClick","onFocus","onKeyDown","searchable","isNegativeOneAllowed","loopable","disabled","comboboxId","propComboboxId","comboboxRef","propComboboxRef","popupId","propPopupId","popupRef","propPopupRef","defaultVisible","onFocusChange","extendKeyDown","getFocusableElements","getEnterDefaultFocusedIndex","getDefaultFocusedIndex","toggled","visible","enable","show","disable","hide","setToggled","setVisible","comboboxRefCallback","popupRefCallback","focusLast","movementProps","movementContext","currentFocusIndex","activeDescendantId","setActiveDescendantId","event","movementData","isPropagationStopped","key","stopPropagation","preventDefault","current","programmatic","includeDisabled","tabIndexBehavior","getTransitionCallbacks","onEntered","onEntering","onExiting","onExited","disableTransition","handleEntering","callback","skipped","appearing","activeOption","document","getElementById","scrollIntoView","block","focusables","index","option","element","id","handleExiting","isTransitionCompleteSkipped","popupProps","ref","role","comboboxProps","undefined","getMenuProps","props","sheetProps","anchor","width","fixedTo","onRequestClose"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/form/useCombobox.ts"],"sourcesContent":["\"use client\";\nimport {\n useCallback,\n useRef,\n type FocusEventHandler,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n type InputHTMLAttributes,\n type KeyboardEventHandler,\n type MouseEventHandler,\n type Ref,\n type RefCallback,\n type RefObject,\n} from \"react\";\nimport { type MenuProps } from \"../menu/Menu.js\";\nimport { type MenuSheetConfigurableProps } from \"../menu/MenuSheet.js\";\nimport {\n type GetDefaultFocusedIndex,\n type GetFocusableElements,\n type KeyboardMovementExtensionData,\n type KeyboardMovementProviderImplementation,\n type KeyboardMovementProviderOptions,\n} from \"../movement/types.js\";\nimport { useKeyboardMovementProvider } from \"../movement/useKeyboardMovementProvider.js\";\nimport { BELOW_CENTER_ANCHOR } from \"../positioning/constants.js\";\nimport {\n type PositionAnchor,\n type PositionWidth,\n} from \"../positioning/types.js\";\nimport { TRANSITION_CONFIG } from \"../transition/config.js\";\nimport {\n type TransitionCallbacks,\n type TransitionEnterHandler,\n type TransitionExitHandler,\n} from \"../transition/types.js\";\nimport {\n type NonNullMutableRef,\n type UseStateInitializer,\n type UseStateSetter,\n} from \"../types.js\";\nimport { useEnsuredId } from \"../useEnsuredId.js\";\nimport { useEnsuredRef } from \"../useEnsuredRef.js\";\nimport { useEnsuredState } from \"../useEnsuredState.js\";\nimport { tryToSubmitRelatedForm } from \"./utils.js\";\n\nconst noop = (): void => {\n // do nothing\n};\n\n/**\n * @since 6.0.0\n */\nexport const getNonDisabledOptions = (\n container: HTMLElement\n): readonly HTMLElement[] => [\n ...container.querySelectorAll<HTMLLIElement>(\n '[role=\"option\"]:not([aria-disabled])'\n ),\n];\n\n/**\n * @since 6.0.0\n */\nexport type SupportedComboboxPopup = \"listbox\" | \"grid\" | \"dialog\";\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxKeyboardMovementData<\n E extends HTMLElement = HTMLInputElement,\n> extends KeyboardMovementExtensionData<E> {\n show: () => void;\n hide: () => void;\n visible: boolean;\n focusLast: NonNullMutableRef<boolean>;\n}\n\n/**\n * @since 6.0.0\n */\nexport type ExtendComboboxKeyDown<E extends HTMLElement = HTMLInputElement> = (\n movementData: ComboboxKeyboardMovementData<E>\n) => void;\n\n/**\n * @since 6.0.0\n */\nexport type ComboboxKeyboardMovementOptions<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n> = Pick<\n KeyboardMovementProviderOptions<ComboboxEl>,\n | \"onClick\"\n | \"onFocus\"\n | \"onKeyDown\"\n | \"disabled\"\n | \"loopable\"\n | \"searchable\"\n | \"onFocusChange\"\n | \"isNegativeOneAllowed\"\n>;\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxVisibilityOptions {\n /**\n * This can be used to control the popup's visibility and **must** be used\n * along with {@link setVisible}.\n */\n visible?: boolean;\n\n /**\n * Used to control the popup's visibility and should generally be a `useState`\n * setter.\n *\n * @example Controlling the Visibility\n * ```tsx\n * const [visible, setVisible] = useState(false);\n *\n * useCombobox({\n * visible,\n * setVisible,\n * });\n * ```\n */\n setVisible?: UseStateSetter<boolean>;\n\n /**\n * Set this to `true` to have the combobox's popup visible by default.\n *\n * @defaultValue `false`\n */\n defaultVisible?: UseStateInitializer<boolean>;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ConfigurableComboboxOptions<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends ComboboxKeyboardMovementOptions<ComboboxEl>,\n ComboboxVisibilityOptions {\n /**\n * This is the {@link InputHTMLAttributes.form} attribute and is used to\n * attempt submitting a form when the enter key is pressed.\n */\n form?: string;\n\n /**\n * @defaultValue `\"combobox-popup-\" + useId()`\n */\n popupId?: string;\n popupRef?: Ref<PopupEl>;\n\n /**\n * @defaultValue `\"combobox-\" + useId()`\n */\n comboboxId?: string;\n comboboxRef?: Ref<ComboboxEl>;\n\n /**\n * @defaultValue `\"listbox\"`\n */\n popup?: \"listbox\" | \"grid\" | \"dialog\";\n\n /**\n * @defaultValue `false`\n */\n multiselect?: boolean;\n\n extendKeyDown?: ExtendComboboxKeyDown<ComboboxEl>;\n\n /**\n * @defaultValue {@link getNonDisabledOptions}\n */\n getFocusableElements?: GetFocusableElements;\n\n getDefaultFocusedIndex?: GetDefaultFocusedIndex;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxGetEnterDefaultFocusedIndexOptions {\n focusLast: boolean;\n focusables: readonly HTMLElement[];\n currentFocusIndex: number;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxOptions<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends ConfigurableComboboxOptions<ComboboxEl, PopupEl> {\n getEnterDefaultFocusedIndex: (\n options: ComboboxGetEnterDefaultFocusedIndexOptions\n ) => number;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxWidgetProps<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n> {\n \"aria-controls\": string;\n \"aria-disabled\": true | undefined;\n \"aria-expanded\": boolean;\n \"aria-haspopup\": SupportedComboboxPopup;\n id: string;\n ref: RefCallback<ComboboxEl>;\n role: \"combobox\";\n onClick: MouseEventHandler<ComboboxEl>;\n onFocus: FocusEventHandler<ComboboxEl>;\n onKeyDown: KeyboardEventHandler<ComboboxEl>;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxWidgetPopupProps<\n PopupEl extends HTMLElement = HTMLElement,\n> {\n \"aria-multiselectable\": true | undefined;\n id: string;\n ref: RefCallback<PopupEl>;\n role: \"listbox\" | \"dialog\" | \"grid\";\n}\n\n/**\n * @since 6.0.0\n */\nexport type ComboboxTransitionCallbacks = Pick<\n TransitionCallbacks,\n \"onEntering\" | \"onEntered\" | \"onExiting\" | \"onExited\"\n>;\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxTransitionOptions extends ComboboxTransitionCallbacks {\n disableTransition?: boolean;\n}\n\n/**\n * @since 6.0.0\n */\nexport type ConfigurableComboboxMenuProps = Partial<\n Omit<MenuProps, \"visible\" | \"onRequestClose\" | keyof ComboboxWidgetPopupProps>\n>;\n\n/**\n * @since 6.0.0\n */\nexport interface ProvidedComboboxMenuProps<\n PopupEl extends HTMLElement = HTMLDivElement,\n> extends Required<ComboboxTransitionCallbacks>,\n ComboboxWidgetPopupProps<PopupEl> {\n visible: boolean;\n onRequestClose: () => void;\n /** @defaultValue `\"min\"` */\n width: PositionWidth;\n /** @defaultValue `BELOW_CENTER_ANCHOR` */\n anchor: PositionAnchor;\n fixedTo: RefObject<HTMLElement>;\n sheetProps: MenuSheetConfigurableProps &\n Required<ComboboxTransitionCallbacks>;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxMenuProps<PopupEl extends HTMLElement = HTMLDivElement>\n extends Omit<ConfigurableComboboxMenuProps, keyof ProvidedComboboxMenuProps>,\n ProvidedComboboxMenuProps<PopupEl> {}\n\n/**\n * @since 6.0.0\n */\nexport interface ComboboxImplementation<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends KeyboardMovementProviderImplementation<ComboboxEl> {\n show: () => void;\n hide: () => void;\n visible: boolean;\n setVisible: UseStateSetter<boolean>;\n focusLast: NonNullMutableRef<boolean>;\n popupRef: RefObject<PopupEl>;\n popupProps: ComboboxWidgetPopupProps<PopupEl>;\n comboboxRef: RefObject<ComboboxEl>;\n comboboxProps: ComboboxWidgetProps<ComboboxEl>;\n /**\n * Since the combobox usually uses the `Menu` as a popup element, this is a\n * helper util to create the required props and merge any additional props\n * with reasonable defaults.\n */\n getMenuProps: (\n overrides?: ConfigurableComboboxMenuProps\n ) => ComboboxMenuProps<PopupEl>;\n getTransitionCallbacks: (\n options: ComboboxTransitionOptions\n ) => Required<ComboboxTransitionCallbacks>;\n}\n\n/**\n * @since 6.0.0\n */\nexport function useCombobox<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n>(\n options: ComboboxOptions<ComboboxEl, PopupEl>\n): ComboboxImplementation<ComboboxEl, PopupEl> {\n const {\n form,\n popup = \"listbox\",\n onClick = noop,\n onFocus,\n onKeyDown,\n searchable,\n multiselect,\n isNegativeOneAllowed,\n loopable,\n disabled,\n visible: propVisible,\n setVisible: propSetVisible,\n defaultVisible = false,\n comboboxId: propComboboxId,\n comboboxRef: propComboboxRef,\n popupId: propPopupId,\n popupRef: propPopupRef,\n onFocusChange = noop,\n extendKeyDown = noop,\n getFocusableElements = getNonDisabledOptions,\n getEnterDefaultFocusedIndex,\n getDefaultFocusedIndex,\n } = options;\n\n const [visible, setVisible] = useEnsuredState({\n value: propVisible,\n setValue: propSetVisible,\n defaultValue: defaultVisible,\n });\n const show = useCallback(() => {\n setVisible(true);\n }, [setVisible]);\n const hide = useCallback(() => {\n setVisible(false);\n }, [setVisible]);\n\n const popupId = useEnsuredId(propPopupId, \"combobox-popup\");\n const comboboxId = useEnsuredId(propComboboxId, \"combobox\");\n const [comboboxRef, comboboxRefCallback] = useEnsuredRef(propComboboxRef);\n const [popupRef, popupRefCallback] = useEnsuredRef(propPopupRef);\n const focusLast = useRef(false);\n const {\n movementProps,\n movementContext,\n currentFocusIndex,\n activeDescendantId,\n setActiveDescendantId,\n } = useKeyboardMovementProvider<ComboboxEl>({\n onFocus,\n onKeyDown,\n onClick(event) {\n onClick(event);\n if (disabled) {\n return;\n }\n\n show();\n },\n extendKeyDown(movementData) {\n extendKeyDown({\n ...movementData,\n show,\n hide,\n visible,\n focusLast,\n });\n const { event } = movementData;\n if (event.isPropagationStopped()) {\n return;\n }\n\n if (visible) {\n switch (event.key) {\n case \"Tab\":\n case \"Escape\":\n event.stopPropagation();\n hide();\n break;\n case \"Enter\":\n event.preventDefault();\n break;\n }\n\n // while visible, always use the default keyboard movement behavior\n return;\n }\n\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowDown\":\n event.preventDefault();\n event.stopPropagation();\n focusLast.current = event.key === \"ArrowUp\";\n show();\n break;\n case \"Enter\":\n tryToSubmitRelatedForm(event, form);\n break;\n }\n },\n disabled,\n loopable,\n searchable,\n onFocusChange,\n programmatic: true,\n includeDisabled: false,\n tabIndexBehavior: \"virtual\",\n getFocusableElements(container, programmatic) {\n const popup = popupRef.current;\n if (!popup) {\n return [];\n }\n\n return getFocusableElements(popup || container, programmatic);\n },\n isNegativeOneAllowed,\n getDefaultFocusedIndex,\n });\n const getTransitionCallbacks = (\n options: ComboboxTransitionOptions = {}\n ): Required<ComboboxTransitionCallbacks> => {\n const { onEntered, onEntering, onExiting, onExited, disableTransition } =\n options;\n\n const handleEntering =\n (callback: TransitionEnterHandler = noop, skipped: boolean) =>\n (appearing: boolean) => {\n callback(appearing);\n\n const popup = popupRef.current;\n if (!popup || skipped) {\n // Chrome does not trigger the scrollIntoView behavior correctly while\n // using a scale transition, so need to trigger this on the entered\n // flow to really make sure the item is in view.\n // An alternative would be to implement a custom scrollIntoView\n // behavior again like the previous versions of react-md, but this is\n // less lines of code\n const activeOption = document.getElementById(activeDescendantId);\n if (activeOption) {\n activeOption.scrollIntoView({ block: \"nearest\" });\n }\n return;\n }\n\n const focusables = getFocusableElements(popup, true);\n const index = getEnterDefaultFocusedIndex({\n focusLast: focusLast.current,\n focusables,\n currentFocusIndex: currentFocusIndex.current,\n });\n focusLast.current = false;\n currentFocusIndex.current = index;\n\n const option = focusables[index];\n if (!option) {\n return;\n }\n\n onFocusChange({\n index,\n element: option,\n });\n\n option.scrollIntoView({ block: \"nearest\" });\n setActiveDescendantId(option.id || \"\");\n };\n const handleExiting =\n (callback: TransitionExitHandler = noop, skipped: boolean) =>\n (): void => {\n callback();\n\n if (!skipped) {\n // since the menu is unmounted or set to hidden while not visible, need\n // to clear the aria-activedescendant and current focus index when\n // hiding\n currentFocusIndex.current = -1;\n setActiveDescendantId(\"\");\n }\n };\n\n const isTransitionCompleteSkipped =\n !disableTransition && !TRANSITION_CONFIG.disabled;\n\n return {\n onEntering: handleEntering(onEntering, false),\n onEntered: handleEntering(onEntered, isTransitionCompleteSkipped),\n onExiting: handleExiting(onExiting, false),\n onExited: handleExiting(onExited, isTransitionCompleteSkipped),\n };\n };\n\n const popupProps: ComboboxWidgetPopupProps<PopupEl> = {\n \"aria-multiselectable\": multiselect || undefined,\n id: popupId,\n ref: popupRefCallback,\n role: popup,\n };\n\n return {\n show,\n hide,\n visible,\n setVisible,\n focusLast,\n popupRef,\n popupProps,\n comboboxRef,\n comboboxProps: {\n ...movementProps,\n \"aria-controls\": popupId,\n \"aria-disabled\": disabled || undefined,\n \"aria-expanded\": visible,\n \"aria-haspopup\": popup,\n id: comboboxId,\n ref: comboboxRefCallback,\n role: \"combobox\",\n },\n movementProps,\n movementContext,\n currentFocusIndex,\n activeDescendantId,\n setActiveDescendantId,\n getTransitionCallbacks,\n getMenuProps(props = {}) {\n const { sheetProps, disableTransition } = props;\n return {\n anchor: BELOW_CENTER_ANCHOR,\n width: \"min\",\n fixedTo: comboboxRef,\n ...props,\n ...popupProps,\n visible,\n onRequestClose: hide,\n ...getTransitionCallbacks(props),\n sheetProps: {\n ...sheetProps,\n ...getTransitionCallbacks({\n ...sheetProps,\n disableTransition:\n sheetProps?.disableTransition ?? disableTransition,\n }),\n },\n };\n },\n };\n}\n"],"names":["useCallback","useRef","useKeyboardMovementProvider","BELOW_CENTER_ANCHOR","TRANSITION_CONFIG","useEnsuredId","useEnsuredRef","useEnsuredState","tryToSubmitRelatedForm","noop","getNonDisabledOptions","container","querySelectorAll","useCombobox","options","form","popup","onClick","onFocus","onKeyDown","searchable","multiselect","isNegativeOneAllowed","loopable","disabled","visible","propVisible","setVisible","propSetVisible","defaultVisible","comboboxId","propComboboxId","comboboxRef","propComboboxRef","popupId","propPopupId","popupRef","propPopupRef","onFocusChange","extendKeyDown","getFocusableElements","getEnterDefaultFocusedIndex","getDefaultFocusedIndex","value","setValue","defaultValue","show","hide","comboboxRefCallback","popupRefCallback","focusLast","movementProps","movementContext","currentFocusIndex","activeDescendantId","setActiveDescendantId","event","movementData","isPropagationStopped","key","stopPropagation","preventDefault","current","programmatic","includeDisabled","tabIndexBehavior","getTransitionCallbacks","onEntered","onEntering","onExiting","onExited","disableTransition","handleEntering","callback","skipped","appearing","activeOption","document","getElementById","scrollIntoView","block","focusables","index","option","element","id","handleExiting","isTransitionCompleteSkipped","popupProps","undefined","ref","role","comboboxProps","getMenuProps","props","sheetProps","anchor","width","fixedTo","onRequestClose"],"mappings":"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"}
@@ -1,15 +1,35 @@
1
- import { type BaseComboboxOptions, type ComboboxImplementation } from "./useCombobox.js";
1
+ import { type ComboboxImplementation, type ComboboxWidgetProps, type ConfigurableComboboxOptions } from "./useCombobox.js";
2
+ import { type EditableHTMLElement } from "./utils.js";
2
3
  /**
3
4
  * @since 6.0.0
4
5
  */
5
- export interface EditableComboboxOptions<ComboboxEl extends HTMLElement = HTMLInputElement, PopupEl extends HTMLElement = HTMLElement> extends BaseComboboxOptions<ComboboxEl, PopupEl> {
6
+ export type EditableComboboxOptions<ComboboxEl extends HTMLElement = HTMLInputElement, PopupEl extends HTMLElement = HTMLElement> = ConfigurableComboboxOptions<ComboboxEl, PopupEl>;
7
+ /**
8
+ * @since 6.0.0
9
+ */
10
+ export interface EditableComboboxWidgetProps<ComboboxEl extends EditableHTMLElement = HTMLInputElement> extends ComboboxWidgetProps<ComboboxEl> {
11
+ /**
12
+ * This is set to `off` to prevent browser from providing their own
13
+ * suggestions.
14
+ *
15
+ * @defaultValue `"off"`
16
+ */
17
+ autoComplete: string;
18
+ /**
19
+ * This is set to `"none"` to prevent browsers from automatically capitalizing
20
+ * the first letter.
21
+ *
22
+ * @defaultValue `"none"`
23
+ */
24
+ autoCapitalize: string;
6
25
  }
7
26
  /**
8
27
  * @since 6.0.0
9
28
  */
10
- export interface EditableComboboxImplementation<ComboboxEl extends HTMLElement = HTMLInputElement, PopupEl extends HTMLElement = HTMLElement> extends ComboboxImplementation<ComboboxEl, PopupEl> {
29
+ export interface EditableComboboxImplementation<ComboboxEl extends EditableHTMLElement = HTMLInputElement, PopupEl extends HTMLElement = HTMLElement> extends ComboboxImplementation<ComboboxEl, PopupEl> {
30
+ comboboxProps: EditableComboboxWidgetProps<ComboboxEl>;
11
31
  }
12
32
  /**
13
33
  * @since 6.0.0
14
34
  */
15
- export declare function useEditableCombobox<ComboboxEl extends HTMLElement = HTMLInputElement, PopupEl extends HTMLElement = HTMLElement>(options?: EditableComboboxOptions<ComboboxEl, PopupEl>): EditableComboboxImplementation<ComboboxEl, PopupEl>;
35
+ export declare function useEditableCombobox<ComboboxEl extends EditableHTMLElement = HTMLInputElement, PopupEl extends HTMLElement = HTMLElement>(options?: EditableComboboxOptions<ComboboxEl, PopupEl>): EditableComboboxImplementation<ComboboxEl, PopupEl>;
@@ -89,6 +89,11 @@ import { isChangeableHTMLElement, triggerManualChangeEvent } from "./utils.js";
89
89
  });
90
90
  return {
91
91
  ...combobox,
92
+ comboboxProps: {
93
+ ...combobox.comboboxProps,
94
+ autoCapitalize: "none",
95
+ autoComplete: "off"
96
+ },
92
97
  getMenuProps (props) {
93
98
  return {
94
99
  // override the inherited renderAsSheet context since the sheet makes it
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/form/useEditableCombobox.ts"],"sourcesContent":["\"use client\";\nimport { useRef } from \"react\";\nimport { isTypeEvent } from \"../movement/utils.js\";\nimport {\n useCombobox,\n type BaseComboboxOptions,\n type ComboboxImplementation,\n} from \"./useCombobox.js\";\nimport { isChangeableHTMLElement, triggerManualChangeEvent } from \"./utils.js\";\n\n/**\n * @since 6.0.0\n */\nexport interface EditableComboboxOptions<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends BaseComboboxOptions<ComboboxEl, PopupEl> {}\n\n/**\n * @since 6.0.0\n */\nexport interface EditableComboboxImplementation<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends ComboboxImplementation<ComboboxEl, PopupEl> {}\n\n/**\n * @since 6.0.0\n */\nexport function useEditableCombobox<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n>(\n options: EditableComboboxOptions<ComboboxEl, PopupEl> = {}\n): EditableComboboxImplementation<ComboboxEl, PopupEl> {\n const focusFirst = useRef(false);\n const { getMenuProps, ...combobox } = useCombobox({\n ...options,\n loopable: true,\n searchable: false,\n isNegativeOneAllowed: true,\n getEnterDefaultFocusedIndex(options) {\n const { focusLast, focusables, currentFocusIndex } = options;\n if (focusFirst.current) {\n focusFirst.current = false;\n return 0;\n }\n\n if (focusLast) {\n return focusables.length - 1;\n }\n\n return currentFocusIndex;\n },\n extendKeyDown(movementData) {\n const {\n event,\n show,\n hide,\n visible,\n currentFocusIndex,\n setActiveDescendantId,\n } = movementData;\n\n const resetFocus = (): void => {\n currentFocusIndex.current = -1;\n setActiveDescendantId(\"\");\n };\n\n switch (event.key) {\n case \"Escape\":\n if (!visible && isChangeableHTMLElement(event.currentTarget)) {\n event.preventDefault();\n event.stopPropagation();\n triggerManualChangeEvent(event.currentTarget, \"\");\n }\n break;\n case \"Home\":\n case \"End\":\n // do not attempt to jump to the start or end of the listbox so\n // natural text editing occurs\n event.stopPropagation();\n if (visible) {\n resetFocus();\n }\n break;\n case \"ArrowLeft\":\n case \"ArrowRight\":\n if (visible) {\n resetFocus();\n }\n break;\n case \"ArrowUp\":\n // Note: The non-altKey version is handled in the `useCombobox` hook\n //\n // if the popup is available and the altKey was pressed, return focus\n // to the combobox without closing. If the focus was already on the\n // combobox, hide the popup\n if (visible && event.altKey) {\n event.preventDefault();\n event.stopPropagation();\n\n if (currentFocusIndex.current !== -1) {\n resetFocus();\n } else {\n hide();\n }\n }\n break;\n case \"ArrowDown\":\n // if the popup is available, display the popup keep the focus on the\n // combobox if the altKey was pressed. Otherwise, move focus into the\n // listbox\n if (!visible) {\n event.preventDefault();\n event.stopPropagation();\n focusFirst.current = !event.altKey;\n show();\n }\n break;\n default:\n if (isTypeEvent(event)) {\n show();\n resetFocus();\n }\n }\n },\n });\n\n return {\n ...combobox,\n getMenuProps(props) {\n return {\n // override the inherited renderAsSheet context since the sheet makes it\n // so the user can't actually type in the combobox\n renderAsSheet: false,\n preventOverlap: true,\n ...getMenuProps(props),\n };\n },\n };\n}\n"],"names":["useRef","isTypeEvent","useCombobox","isChangeableHTMLElement","triggerManualChangeEvent","useEditableCombobox","options","focusFirst","getMenuProps","combobox","loopable","searchable","isNegativeOneAllowed","getEnterDefaultFocusedIndex","focusLast","focusables","currentFocusIndex","current","length","extendKeyDown","movementData","event","show","hide","visible","setActiveDescendantId","resetFocus","key","currentTarget","preventDefault","stopPropagation","altKey","props","renderAsSheet","preventOverlap"],"mappings":"AAAA;AACA,SAASA,MAAM,QAAQ,QAAQ;AAC/B,SAASC,WAAW,QAAQ,uBAAuB;AACnD,SACEC,WAAW,QAGN,mBAAmB;AAC1B,SAASC,uBAAuB,EAAEC,wBAAwB,QAAQ,aAAa;AAkB/E;;CAEC,GACD,OAAO,SAASC,oBAIdC,UAAwD,CAAC,CAAC;IAE1D,MAAMC,aAAaP,OAAO;IAC1B,MAAM,EAAEQ,YAAY,EAAE,GAAGC,UAAU,GAAGP,YAAY;QAChD,GAAGI,OAAO;QACVI,UAAU;QACVC,YAAY;QACZC,sBAAsB;QACtBC,6BAA4BP,OAAO;YACjC,MAAM,EAAEQ,SAAS,EAAEC,UAAU,EAAEC,iBAAiB,EAAE,GAAGV;YACrD,IAAIC,WAAWU,OAAO,EAAE;gBACtBV,WAAWU,OAAO,GAAG;gBACrB,OAAO;YACT;YAEA,IAAIH,WAAW;gBACb,OAAOC,WAAWG,MAAM,GAAG;YAC7B;YAEA,OAAOF;QACT;QACAG,eAAcC,YAAY;YACxB,MAAM,EACJC,KAAK,EACLC,IAAI,EACJC,IAAI,EACJC,OAAO,EACPR,iBAAiB,EACjBS,qBAAqB,EACtB,GAAGL;YAEJ,MAAMM,aAAa;gBACjBV,kBAAkBC,OAAO,GAAG,CAAC;gBAC7BQ,sBAAsB;YACxB;YAEA,OAAQJ,MAAMM,GAAG;gBACf,KAAK;oBACH,IAAI,CAACH,WAAWrB,wBAAwBkB,MAAMO,aAAa,GAAG;wBAC5DP,MAAMQ,cAAc;wBACpBR,MAAMS,eAAe;wBACrB1B,yBAAyBiB,MAAMO,aAAa,EAAE;oBAChD;oBACA;gBACF,KAAK;gBACL,KAAK;oBACH,+DAA+D;oBAC/D,8BAA8B;oBAC9BP,MAAMS,eAAe;oBACrB,IAAIN,SAAS;wBACXE;oBACF;oBACA;gBACF,KAAK;gBACL,KAAK;oBACH,IAAIF,SAAS;wBACXE;oBACF;oBACA;gBACF,KAAK;oBACH,oEAAoE;oBACpE,EAAE;oBACF,qEAAqE;oBACrE,mEAAmE;oBACnE,2BAA2B;oBAC3B,IAAIF,WAAWH,MAAMU,MAAM,EAAE;wBAC3BV,MAAMQ,cAAc;wBACpBR,MAAMS,eAAe;wBAErB,IAAId,kBAAkBC,OAAO,KAAK,CAAC,GAAG;4BACpCS;wBACF,OAAO;4BACLH;wBACF;oBACF;oBACA;gBACF,KAAK;oBACH,qEAAqE;oBACrE,qEAAqE;oBACrE,UAAU;oBACV,IAAI,CAACC,SAAS;wBACZH,MAAMQ,cAAc;wBACpBR,MAAMS,eAAe;wBACrBvB,WAAWU,OAAO,GAAG,CAACI,MAAMU,MAAM;wBAClCT;oBACF;oBACA;gBACF;oBACE,IAAIrB,YAAYoB,QAAQ;wBACtBC;wBACAI;oBACF;YACJ;QACF;IACF;IAEA,OAAO;QACL,GAAGjB,QAAQ;QACXD,cAAawB,KAAK;YAChB,OAAO;gBACL,wEAAwE;gBACxE,kDAAkD;gBAClDC,eAAe;gBACfC,gBAAgB;gBAChB,GAAG1B,aAAawB,MAAM;YACxB;QACF;IACF;AACF"}
1
+ {"version":3,"sources":["../../src/form/useEditableCombobox.ts"],"sourcesContent":["\"use client\";\nimport { useRef } from \"react\";\nimport { isTypeEvent } from \"../movement/utils.js\";\nimport {\n type ComboboxImplementation,\n type ComboboxWidgetProps,\n type ConfigurableComboboxOptions,\n useCombobox,\n} from \"./useCombobox.js\";\nimport {\n type EditableHTMLElement,\n isChangeableHTMLElement,\n triggerManualChangeEvent,\n} from \"./utils.js\";\n\n/**\n * @since 6.0.0\n */\nexport type EditableComboboxOptions<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> = ConfigurableComboboxOptions<ComboboxEl, PopupEl>;\n\n/**\n * @since 6.0.0\n */\nexport interface EditableComboboxWidgetProps<\n ComboboxEl extends EditableHTMLElement = HTMLInputElement,\n> extends ComboboxWidgetProps<ComboboxEl> {\n /**\n * This is set to `off` to prevent browser from providing their own\n * suggestions.\n *\n * @defaultValue `\"off\"`\n */\n autoComplete: string;\n\n /**\n * This is set to `\"none\"` to prevent browsers from automatically capitalizing\n * the first letter.\n *\n * @defaultValue `\"none\"`\n */\n autoCapitalize: string;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface EditableComboboxImplementation<\n ComboboxEl extends EditableHTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends ComboboxImplementation<ComboboxEl, PopupEl> {\n comboboxProps: EditableComboboxWidgetProps<ComboboxEl>;\n}\n\n/**\n * @since 6.0.0\n */\nexport function useEditableCombobox<\n ComboboxEl extends EditableHTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n>(\n options: EditableComboboxOptions<ComboboxEl, PopupEl> = {}\n): EditableComboboxImplementation<ComboboxEl, PopupEl> {\n const focusFirst = useRef(false);\n const { getMenuProps, ...combobox } = useCombobox({\n ...options,\n loopable: true,\n searchable: false,\n isNegativeOneAllowed: true,\n getEnterDefaultFocusedIndex(options) {\n const { focusLast, focusables, currentFocusIndex } = options;\n if (focusFirst.current) {\n focusFirst.current = false;\n return 0;\n }\n\n if (focusLast) {\n return focusables.length - 1;\n }\n\n return currentFocusIndex;\n },\n extendKeyDown(movementData) {\n const {\n event,\n show,\n hide,\n visible,\n currentFocusIndex,\n setActiveDescendantId,\n } = movementData;\n\n const resetFocus = (): void => {\n currentFocusIndex.current = -1;\n setActiveDescendantId(\"\");\n };\n\n switch (event.key) {\n case \"Escape\":\n if (!visible && isChangeableHTMLElement(event.currentTarget)) {\n event.preventDefault();\n event.stopPropagation();\n triggerManualChangeEvent(event.currentTarget, \"\");\n }\n break;\n case \"Home\":\n case \"End\":\n // do not attempt to jump to the start or end of the listbox so\n // natural text editing occurs\n event.stopPropagation();\n if (visible) {\n resetFocus();\n }\n break;\n case \"ArrowLeft\":\n case \"ArrowRight\":\n if (visible) {\n resetFocus();\n }\n break;\n case \"ArrowUp\":\n // Note: The non-altKey version is handled in the `useCombobox` hook\n //\n // if the popup is available and the altKey was pressed, return focus\n // to the combobox without closing. If the focus was already on the\n // combobox, hide the popup\n if (visible && event.altKey) {\n event.preventDefault();\n event.stopPropagation();\n\n if (currentFocusIndex.current !== -1) {\n resetFocus();\n } else {\n hide();\n }\n }\n break;\n case \"ArrowDown\":\n // if the popup is available, display the popup keep the focus on the\n // combobox if the altKey was pressed. Otherwise, move focus into the\n // listbox\n if (!visible) {\n event.preventDefault();\n event.stopPropagation();\n focusFirst.current = !event.altKey;\n show();\n }\n break;\n default:\n if (isTypeEvent(event)) {\n show();\n resetFocus();\n }\n }\n },\n });\n\n return {\n ...combobox,\n comboboxProps: {\n ...combobox.comboboxProps,\n autoCapitalize: \"none\",\n autoComplete: \"off\",\n },\n getMenuProps(props) {\n return {\n // override the inherited renderAsSheet context since the sheet makes it\n // so the user can't actually type in the combobox\n renderAsSheet: false,\n preventOverlap: true,\n ...getMenuProps(props),\n };\n },\n };\n}\n"],"names":["useRef","isTypeEvent","useCombobox","isChangeableHTMLElement","triggerManualChangeEvent","useEditableCombobox","options","focusFirst","getMenuProps","combobox","loopable","searchable","isNegativeOneAllowed","getEnterDefaultFocusedIndex","focusLast","focusables","currentFocusIndex","current","length","extendKeyDown","movementData","event","show","hide","visible","setActiveDescendantId","resetFocus","key","currentTarget","preventDefault","stopPropagation","altKey","comboboxProps","autoCapitalize","autoComplete","props","renderAsSheet","preventOverlap"],"mappings":"AAAA;AACA,SAASA,MAAM,QAAQ,QAAQ;AAC/B,SAASC,WAAW,QAAQ,uBAAuB;AACnD,SAIEC,WAAW,QACN,mBAAmB;AAC1B,SAEEC,uBAAuB,EACvBC,wBAAwB,QACnB,aAAa;AA2CpB;;CAEC,GACD,OAAO,SAASC,oBAIdC,UAAwD,CAAC,CAAC;IAE1D,MAAMC,aAAaP,OAAO;IAC1B,MAAM,EAAEQ,YAAY,EAAE,GAAGC,UAAU,GAAGP,YAAY;QAChD,GAAGI,OAAO;QACVI,UAAU;QACVC,YAAY;QACZC,sBAAsB;QACtBC,6BAA4BP,OAAO;YACjC,MAAM,EAAEQ,SAAS,EAAEC,UAAU,EAAEC,iBAAiB,EAAE,GAAGV;YACrD,IAAIC,WAAWU,OAAO,EAAE;gBACtBV,WAAWU,OAAO,GAAG;gBACrB,OAAO;YACT;YAEA,IAAIH,WAAW;gBACb,OAAOC,WAAWG,MAAM,GAAG;YAC7B;YAEA,OAAOF;QACT;QACAG,eAAcC,YAAY;YACxB,MAAM,EACJC,KAAK,EACLC,IAAI,EACJC,IAAI,EACJC,OAAO,EACPR,iBAAiB,EACjBS,qBAAqB,EACtB,GAAGL;YAEJ,MAAMM,aAAa;gBACjBV,kBAAkBC,OAAO,GAAG,CAAC;gBAC7BQ,sBAAsB;YACxB;YAEA,OAAQJ,MAAMM,GAAG;gBACf,KAAK;oBACH,IAAI,CAACH,WAAWrB,wBAAwBkB,MAAMO,aAAa,GAAG;wBAC5DP,MAAMQ,cAAc;wBACpBR,MAAMS,eAAe;wBACrB1B,yBAAyBiB,MAAMO,aAAa,EAAE;oBAChD;oBACA;gBACF,KAAK;gBACL,KAAK;oBACH,+DAA+D;oBAC/D,8BAA8B;oBAC9BP,MAAMS,eAAe;oBACrB,IAAIN,SAAS;wBACXE;oBACF;oBACA;gBACF,KAAK;gBACL,KAAK;oBACH,IAAIF,SAAS;wBACXE;oBACF;oBACA;gBACF,KAAK;oBACH,oEAAoE;oBACpE,EAAE;oBACF,qEAAqE;oBACrE,mEAAmE;oBACnE,2BAA2B;oBAC3B,IAAIF,WAAWH,MAAMU,MAAM,EAAE;wBAC3BV,MAAMQ,cAAc;wBACpBR,MAAMS,eAAe;wBAErB,IAAId,kBAAkBC,OAAO,KAAK,CAAC,GAAG;4BACpCS;wBACF,OAAO;4BACLH;wBACF;oBACF;oBACA;gBACF,KAAK;oBACH,qEAAqE;oBACrE,qEAAqE;oBACrE,UAAU;oBACV,IAAI,CAACC,SAAS;wBACZH,MAAMQ,cAAc;wBACpBR,MAAMS,eAAe;wBACrBvB,WAAWU,OAAO,GAAG,CAACI,MAAMU,MAAM;wBAClCT;oBACF;oBACA;gBACF;oBACE,IAAIrB,YAAYoB,QAAQ;wBACtBC;wBACAI;oBACF;YACJ;QACF;IACF;IAEA,OAAO;QACL,GAAGjB,QAAQ;QACXuB,eAAe;YACb,GAAGvB,SAASuB,aAAa;YACzBC,gBAAgB;YAChBC,cAAc;QAChB;QACA1B,cAAa2B,KAAK;YAChB,OAAO;gBACL,wEAAwE;gBACxE,kDAAkD;gBAClDC,eAAe;gBACfC,gBAAgB;gBAChB,GAAG7B,aAAa2B,MAAM;YACxB;QACF;IACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/form/useNumberField.ts"],"sourcesContent":["\"use client\";\nimport { useCallback, useRef, useState } from \"react\";\nimport { type UseStateInitializer, type UseStateSetter } from \"../types.js\";\nimport { withinRange } from \"../utils/withinRange.js\";\nimport {\n useTextField,\n type ProvidedTextFieldMessageProps,\n type ProvidedTextFieldProps,\n type TextFieldHookOptions,\n type TextFieldHookState,\n type TextFieldImplementation,\n type ValidatedTextFieldImplementation,\n} from \"./useTextField.js\";\n\nconst noop = (): void => {\n // do nothing\n};\n\n/** @since 2.5.0 */\nexport interface NumberFieldConstraints {\n /**\n * An optional min value for the number field.\n */\n min?: number;\n\n /**\n * An optional max value for the number field.\n */\n max?: number;\n\n /**\n * An optional step amount to use.\n *\n * Note: The `min` and `max` values must be divisible by this value when any\n * are defined.\n */\n step?: number;\n}\n\n/**\n * @since 2.5.0\n * @since 6.0.0\n * - Removed `updateOnChange` in favor of `updateValue`\n * - Renamed `fixOnBlur` to `updateValueOnBlur`\n */\nexport interface NumberFieldHookOptions\n extends Omit<\n TextFieldHookOptions<HTMLInputElement>,\n \"defaultValue\" | \"isNumber\"\n >,\n NumberFieldConstraints {\n /**\n * @defaultValue `undefined`\n */\n defaultValue?: UseStateInitializer<number>;\n\n /**\n * This controls the behavior for the `value` returned by this hook. If you\n * need access to the current value immediately as the user types to update\n * other components, keep this as the default of `\"change\"`. Otherwise, set\n * this to `\"blur\"`.\n *\n * @example Deferring Updates on Blur\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * min: 0,\n * max: 100,\n * name: \"someName\",\n * defaultValue: 0,\n * updateValue: \"blur\",\n * });\n *\n * const result = useMemo(() => someExpensiveComputation(value), [value]);\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @defaultValue `\"change\"`\n */\n updateValue?: \"blur\" | \"change\";\n\n /**\n * This option is used to update the `number` value and text field value to be\n * within the `min` and `max` range or just format the text field value when\n * the input is blurred. This update will only be applied if the text field\n * contains a valid number. Using `min = 0` and `max = 10`:\n *\n * | text value | updated value |\n * | ---------- | ------------- |\n * | 000001 | 1 |\n * | -1 | 0 |\n * | 20 | 10 |\n * | -12 | 0 |\n * | --1 | --1 |\n * | fjdka | fjdka |\n *\n *\n * Set this to `false` if no changed should be applied and force the user to\n * fix any min/max errors manually and maintain weird formatting.\n *\n * @defaultValue `true`\n * @since 6.0.0 This was renamed from `fixOnBlur` and removed the\n * `\"min\"` and `\"max\"` behavior.\n */\n updateValueOnBlur?: boolean;\n}\n\n/** @since 6.0.0 */\nexport interface NumberFieldHookState\n extends Omit<TextFieldHookState, \"value\"> {\n value: number | undefined;\n}\n\n/** @since 2.5.6 */\nexport interface ProvidedNumberFieldProps\n extends ProvidedTextFieldProps<HTMLInputElement>,\n NumberFieldConstraints {\n type: \"number\";\n}\n\n/** @since 2.5.6 */\nexport interface ProvidedNumberFieldMessageProps\n extends ProvidedTextFieldMessageProps<HTMLInputElement>,\n NumberFieldConstraints {\n type: \"number\";\n}\n\n/** @since 6.0.0 */\nexport interface NumberFieldImplementation\n extends Omit<\n TextFieldImplementation<HTMLInputElement>,\n \"value\" | \"setState\"\n > {\n value: number | undefined;\n setState: UseStateSetter<NumberFieldHookState>;\n fieldProps: ProvidedNumberFieldProps;\n}\n\n/** @since 6.0.0 */\nexport interface NumberFieldWithMessageImplementation\n extends NumberFieldImplementation {\n fieldProps: ProvidedNumberFieldMessageProps;\n}\n\n/** @since 6.0.0 */\nexport interface ValidatedNumberFieldImplementation\n extends Omit<\n ValidatedTextFieldImplementation<HTMLInputElement>,\n \"value\" | \"setState\"\n > {\n value: number | undefined;\n setState: UseStateSetter<NumberFieldHookState>;\n fieldProps: ProvidedNumberFieldProps | ProvidedNumberFieldMessageProps;\n}\n\n/**\n * @example Enforce Number Value and No Error Messages\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * min: 0,\n * max: 100,\n * name: \"someName\",\n * defaultValue: 0,\n * disableMessage: true,\n * });\n *\n * // this is safe since `value` will always be a number even if there is a\n * // validation error. since the min and max options were provided as well,\n * // number will be between that range as well.\n * const computed = value * 10;\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n *\n * @see {@link useTextField}\n * @see {@link useNumberField} overrides for other examples.\n * ```\n */\nexport function useNumberField(\n options: NumberFieldHookOptions & {\n disableMessage: true;\n defaultValue: UseStateInitializer<number>;\n }\n): NumberFieldImplementation & {\n value: number;\n setState: UseStateSetter<NumberFieldHookState & { value: number }>;\n};\n\n/**\n * @example No Error Messages\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * min: 0,\n * max: 100,\n * name: \"someName\",\n * disableMessage: true,\n * });\n *\n * // `value` will be `undefined` until the user enters a valid value once\n * // there is a valid value, `value` will be a `number`. So this might cause\n * // `computed` to be `NaN | number`\n * //\n * // const computed = value * 10;\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @see {@link useTextField}\n * @see {@link useNumberField} overrides for other examples.\n */\nexport function useNumberField(\n options: NumberFieldHookOptions & { disableMessage: true }\n): NumberFieldImplementation;\n\n/**\n * @example Enforce Number Value\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * min: 0,\n * max: 100,\n * name: \"someName\",\n * defaultValue: 0,\n * });\n *\n * // this is safe since `value` will always be a number even if there is a\n * // validation error. since the min and max options were provided as well,\n * // number will be between that range as well.\n * const computed = value * 10;\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @example Enforce Number Value and Deferring Updates\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * min: 0,\n * max: 100,\n * name: \"someName\",\n * defaultValue: 0,\n * updateValue: \"blur\",\n * });\n *\n * // the `value` will only be updated whenever the `TextField` is blurred.\n * // This is helpful if the `value` is used in expensive computations or\n * // updates that do not need to be updated as the user types\n * const computed = value * 10;\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @see {@link useTextField}\n * @see {@link useNumberField} overrides for other examples.\n */\nexport function useNumberField(\n options: NumberFieldHookOptions & {\n defaultValue: UseStateInitializer<number>;\n }\n): NumberFieldWithMessageImplementation & {\n value: number;\n setState: UseStateSetter<NumberFieldHookState & { value: number }>;\n};\n\n/**\n * The `useNumberField` hook is used to control the state of a `TextField` or\n * `<input type=\"number\">`\n *\n * @example Default Implementation\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * name: \"someName\",\n * });\n *\n * // `value` will be `undefined` until the user enters a valid value once\n * // there is a valid value, `value` will be a `number`. So this might cause\n * // `computed` to be `NaN | number`\n * //\n * // const computed = value * 10;\n *\n * // whenever there is an error, an error message will be displayed below the\n * // `TextField`\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @example Adding Constraints\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * name: \"someName\",\n * min: 0,\n * max: 100,\n * step: 2,\n * required: true,\n * });\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation\n * @see {@link useTextField}\n */\nexport function useNumberField(\n options: NumberFieldHookOptions\n): NumberFieldWithMessageImplementation;\n\n/**\n * @internal\n * @see {@link useTextField}\n * @see {@link useNumberField} overrides for other examples.\n */\nexport function useNumberField(\n options: NumberFieldHookOptions\n): ValidatedNumberFieldImplementation {\n const {\n min,\n max,\n step,\n onBlur = noop,\n onChange = noop,\n updateValue = \"change\",\n updateValueOnBlur = true,\n defaultValue,\n ...textOptions\n } = options;\n\n const [number, setNumber] = useState(defaultValue);\n const initial = useRef(number);\n const {\n value: _value,\n reset: resetTextField,\n fieldProps,\n setState: setTextFieldState,\n ...remaining\n } = useTextField({\n ...textOptions,\n isNumber: true,\n defaultValue: `${number ?? \"\"}`,\n onBlur(event) {\n onBlur(event);\n if (event.isPropagationStopped()) {\n return;\n }\n\n const input = event.currentTarget;\n input.setCustomValidity(\"\");\n input.checkValidity();\n if (\n !updateValueOnBlur ||\n // do nothing else since it's a weird value like: `\"--0\"` which causes\n // the value to be `\"\"` and `numberAsValue` to be `NaN`\n input.validity.badInput\n ) {\n return;\n }\n\n let value = input.valueAsNumber;\n if (input.value === \"\" && typeof initial.current === \"number\") {\n value = min ?? initial.current;\n }\n\n // can't have both rangeUnderflow and rangeOverflow at the same time, so\n // it's \"safe\" to always provide both\n value = withinRange({ min, max, value });\n if (!Number.isNaN(value)) {\n setNumber(value);\n input.value = `${value}`;\n } else if (typeof initial.current === \"undefined\") {\n setNumber(undefined);\n }\n },\n onChange(event) {\n onChange(event);\n if (event.isPropagationStopped() || updateValue === \"blur\") {\n return;\n }\n\n const input = event.currentTarget;\n input.checkValidity();\n const value = withinRange({\n min,\n max,\n value: event.currentTarget.valueAsNumber,\n });\n if (\n !input.validity.valid &&\n !input.validity.rangeUnderflow &&\n !input.validity.rangeOverflow\n ) {\n return;\n }\n\n if (!Number.isNaN(value)) {\n setNumber(value);\n } else if (initial.current === undefined) {\n setNumber(undefined);\n }\n },\n });\n\n const reset = useCallback(() => {\n resetTextField();\n setNumber(initial.current);\n }, [resetTextField]);\n const setState = useCallback<UseStateSetter<NumberFieldHookState>>(\n (nextState) => {\n if (typeof nextState === \"function\") {\n setNumber((prevNumber) => {\n let nextNumber: number | undefined = prevNumber;\n setTextFieldState((prevState) => {\n const updated = nextState({\n ...prevState,\n value: prevNumber,\n });\n\n nextNumber = updated.value;\n\n return {\n ...updated,\n value: `${nextNumber ?? \"\"}`,\n };\n });\n\n return nextNumber;\n });\n return;\n }\n\n const { value, error, errorMessage } = nextState;\n setNumber(value);\n setTextFieldState({\n value: `${value ?? \"\"}`,\n error,\n errorMessage,\n });\n },\n [setTextFieldState]\n );\n\n return {\n ...remaining,\n reset,\n value: number,\n setState,\n fieldProps: {\n ...fieldProps,\n min,\n max,\n step,\n type: \"number\",\n },\n };\n}\n"],"names":["useCallback","useRef","useState","withinRange","useTextField","noop","useNumberField","options","min","max","step","onBlur","onChange","updateValue","updateValueOnBlur","defaultValue","textOptions","number","setNumber","initial","value","_value","reset","resetTextField","fieldProps","setState","setTextFieldState","remaining","isNumber","event","isPropagationStopped","input","currentTarget","setCustomValidity","checkValidity","validity","badInput","valueAsNumber","current","Number","isNaN","undefined","valid","rangeUnderflow","rangeOverflow","nextState","prevNumber","nextNumber","prevState","updated","error","errorMessage","type"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/form/useNumberField.ts"],"sourcesContent":["\"use client\";\nimport { useCallback, useRef, useState } from \"react\";\nimport { type UseStateInitializer, type UseStateSetter } from \"../types.js\";\nimport { withinRange } from \"../utils/withinRange.js\";\nimport {\n useTextField,\n type ProvidedTextFieldMessageProps,\n type ProvidedTextFieldProps,\n type TextFieldHookOptions,\n type TextFieldHookState,\n type TextFieldImplementation,\n type ValidatedTextFieldImplementation,\n} from \"./useTextField.js\";\n\nconst noop = (): void => {\n // do nothing\n};\n\n/** @since 2.5.0 */\nexport interface NumberFieldConstraints {\n /**\n * An optional min value for the number field.\n */\n min?: number;\n\n /**\n * An optional max value for the number field.\n */\n max?: number;\n\n /**\n * An optional step amount to use.\n *\n * Note: The `min` and `max` values must be divisible by this value when any\n * are defined.\n */\n step?: number;\n}\n\n/**\n * @since 2.5.0\n * @since 6.0.0\n * - Removed `updateOnChange` in favor of `updateValue`\n * - Renamed `fixOnBlur` to `updateValueOnBlur`\n */\nexport interface NumberFieldHookOptions\n extends Omit<\n TextFieldHookOptions<HTMLInputElement>,\n \"defaultValue\" | \"isNumber\"\n >,\n NumberFieldConstraints {\n /**\n * @defaultValue `undefined`\n */\n defaultValue?: UseStateInitializer<number>;\n\n /**\n * This controls the behavior for the `value` returned by this hook. If you\n * need access to the current value immediately as the user types to update\n * other components, keep this as the default of `\"change\"`. Otherwise, set\n * this to `\"blur\"`.\n *\n * @example Deferring Updates on Blur\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * min: 0,\n * max: 100,\n * name: \"someName\",\n * defaultValue: 0,\n * updateValue: \"blur\",\n * });\n *\n * const result = useMemo(() => someExpensiveComputation(value), [value]);\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @defaultValue `\"change\"`\n */\n updateValue?: \"blur\" | \"change\";\n\n /**\n * This option is used to update the `number` value and text field value to be\n * within the `min` and `max` range or just format the text field value when\n * the input is blurred. This update will only be applied if the text field\n * contains a valid number. Using `min = 0` and `max = 10`:\n *\n * | text value | updated value |\n * | ---------- | ------------- |\n * | 000001 | 1 |\n * | -1 | 0 |\n * | 20 | 10 |\n * | -12 | 0 |\n * | --1 | --1 |\n * | fjdka | fjdka |\n *\n *\n * Set this to `false` if no changed should be applied and force the user to\n * fix any min/max errors manually and maintain weird formatting.\n *\n * @defaultValue `true`\n * @since 6.0.0 This was renamed from `fixOnBlur` and removed the\n * `\"min\"` and `\"max\"` behavior.\n */\n updateValueOnBlur?: boolean;\n}\n\n/** @since 6.0.0 */\nexport interface NumberFieldHookState\n extends Omit<TextFieldHookState, \"value\"> {\n value: number | undefined;\n}\n\n/** @since 2.5.6 */\nexport interface ProvidedNumberFieldProps\n extends ProvidedTextFieldProps<HTMLInputElement>,\n NumberFieldConstraints {\n type: \"number\";\n}\n\n/** @since 2.5.6 */\nexport interface ProvidedNumberFieldMessageProps\n extends ProvidedTextFieldMessageProps<HTMLInputElement>,\n NumberFieldConstraints {\n type: \"number\";\n}\n\n/** @since 6.0.0 */\nexport interface NumberFieldImplementation\n extends Omit<\n TextFieldImplementation<HTMLInputElement>,\n \"value\" | \"setState\"\n > {\n value: number | undefined;\n setState: UseStateSetter<NumberFieldHookState>;\n fieldProps: ProvidedNumberFieldProps;\n}\n\n/** @since 6.0.0 */\nexport interface NumberFieldWithMessageImplementation\n extends NumberFieldImplementation {\n fieldProps: ProvidedNumberFieldMessageProps;\n}\n\n/** @since 6.0.0 */\nexport interface ValidatedNumberFieldImplementation\n extends Omit<\n ValidatedTextFieldImplementation<HTMLInputElement>,\n \"value\" | \"setState\"\n > {\n value: number | undefined;\n setState: UseStateSetter<NumberFieldHookState>;\n fieldProps: ProvidedNumberFieldProps | ProvidedNumberFieldMessageProps;\n}\n\n/**\n * @example Enforce Number Value and No Error Messages\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * min: 0,\n * max: 100,\n * name: \"someName\",\n * defaultValue: 0,\n * disableMessage: true,\n * });\n *\n * // this is safe since `value` will always be a number even if there is a\n * // validation error. since the min and max options were provided as well,\n * // number will be between that range as well.\n * const computed = value * 10;\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n *\n * @see {@link useTextField}\n * @see {@link useNumberField} overrides for other examples.\n * ```\n */\nexport function useNumberField(\n options: NumberFieldHookOptions & {\n disableMessage: true;\n defaultValue: UseStateInitializer<number>;\n }\n): NumberFieldImplementation & {\n value: number;\n setState: UseStateSetter<NumberFieldHookState & { value: number }>;\n};\n\n/**\n * @example No Error Messages\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * min: 0,\n * max: 100,\n * name: \"someName\",\n * disableMessage: true,\n * });\n *\n * // `value` will be `undefined` until the user enters a valid value once\n * // there is a valid value, `value` will be a `number`. So this might cause\n * // `computed` to be `NaN | number`\n * //\n * // const computed = value * 10;\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @see {@link useTextField}\n * @see {@link useNumberField} overrides for other examples.\n */\nexport function useNumberField(\n options: NumberFieldHookOptions & { disableMessage: true }\n): NumberFieldImplementation;\n\n/**\n * @example Enforce Number Value\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * min: 0,\n * max: 100,\n * name: \"someName\",\n * defaultValue: 0,\n * });\n *\n * // this is safe since `value` will always be a number even if there is a\n * // validation error. since the min and max options were provided as well,\n * // number will be between that range as well.\n * const computed = value * 10;\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @example Enforce Number Value and Deferring Updates\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * min: 0,\n * max: 100,\n * name: \"someName\",\n * defaultValue: 0,\n * updateValue: \"blur\",\n * });\n *\n * // the `value` will only be updated whenever the `TextField` is blurred.\n * // This is helpful if the `value` is used in expensive computations or\n * // updates that do not need to be updated as the user types\n * const computed = value * 10;\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @see {@link useTextField}\n * @see {@link useNumberField} overrides for other examples.\n */\nexport function useNumberField(\n options: NumberFieldHookOptions & {\n defaultValue: UseStateInitializer<number>;\n }\n): NumberFieldWithMessageImplementation & {\n value: number;\n setState: UseStateSetter<NumberFieldHookState & { value: number }>;\n};\n\n/**\n * The `useNumberField` hook is used to control the state of a `TextField` or\n * `<input type=\"number\">`\n *\n * @example Default Implementation\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * name: \"someName\",\n * });\n *\n * // `value` will be `undefined` until the user enters a valid value once\n * // there is a valid value, `value` will be a `number`. So this might cause\n * // `computed` to be `NaN | number`\n * //\n * // const computed = value * 10;\n *\n * // whenever there is an error, an error message will be displayed below the\n * // `TextField`\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @example Adding Constraints\n * ```tsx\n * import { TextField, useNumberField } from \"@react-md/core\";\n * import type { ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const { fieldProps, value } = useNumberField({\n * name: \"someName\",\n * min: 0,\n * max: 100,\n * step: 2,\n * required: true,\n * });\n *\n * return <TextField {...fieldProps} label=\"Label\" />;\n * }\n * ```\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation\n * @see {@link useTextField}\n */\nexport function useNumberField(\n options: NumberFieldHookOptions\n): NumberFieldWithMessageImplementation;\n\n/**\n * @internal\n * @see {@link useTextField}\n * @see {@link useNumberField} overrides for other examples.\n */\nexport function useNumberField(\n options: NumberFieldHookOptions\n): ValidatedNumberFieldImplementation {\n const {\n min,\n max,\n step,\n onBlur = noop,\n onChange = noop,\n updateValue = \"change\",\n updateValueOnBlur = true,\n defaultValue,\n ...textOptions\n } = options;\n\n const [number, setNumber] = useState(defaultValue);\n const initial = useRef(number);\n const {\n value: _value,\n reset: resetTextField,\n fieldProps,\n setState: setTextFieldState,\n ...remaining\n } = useTextField({\n ...textOptions,\n isNumber: true,\n defaultValue: `${number ?? \"\"}`,\n onBlur(event) {\n onBlur(event);\n if (event.isPropagationStopped()) {\n return;\n }\n\n const input = event.currentTarget;\n input.setCustomValidity(\"\");\n input.checkValidity();\n if (\n !updateValueOnBlur ||\n // do nothing else since it's a weird value like: `\"--0\"` which causes\n // the value to be `\"\"` and `numberAsValue` to be `NaN`\n input.validity.badInput\n ) {\n return;\n }\n\n let value = input.valueAsNumber;\n if (input.value === \"\" && typeof initial.current === \"number\") {\n value = min ?? initial.current;\n }\n\n // can't have both rangeUnderflow and rangeOverflow at the same time, so\n // it's \"safe\" to always provide both\n value = withinRange({ min, max, value });\n if (!Number.isNaN(value)) {\n setNumber(value);\n input.value = `${value}`;\n } else if (typeof initial.current === \"undefined\") {\n setNumber(undefined);\n }\n },\n onChange(event) {\n onChange(event);\n if (event.isPropagationStopped() || updateValue === \"blur\") {\n return;\n }\n\n const input = event.currentTarget;\n input.checkValidity();\n const value = withinRange({\n min,\n max,\n value: event.currentTarget.valueAsNumber,\n });\n if (\n !input.validity.valid &&\n !input.validity.rangeUnderflow &&\n !input.validity.rangeOverflow\n ) {\n return;\n }\n\n if (!Number.isNaN(value)) {\n setNumber(value);\n } else if (initial.current === undefined) {\n setNumber(undefined);\n }\n },\n });\n\n const reset = useCallback(() => {\n resetTextField();\n setNumber(initial.current);\n }, [resetTextField]);\n const setState = useCallback<UseStateSetter<NumberFieldHookState>>(\n (nextState) => {\n if (typeof nextState === \"function\") {\n setNumber((prevNumber) => {\n let nextNumber: number | undefined = prevNumber;\n setTextFieldState((prevState) => {\n const updated = nextState({\n ...prevState,\n value: prevNumber,\n });\n\n nextNumber = updated.value;\n\n return {\n ...updated,\n value: `${nextNumber ?? \"\"}`,\n };\n });\n\n return nextNumber;\n });\n return;\n }\n\n const { value, error, errorMessage } = nextState;\n setNumber(value);\n setTextFieldState({\n value: `${value ?? \"\"}`,\n error,\n errorMessage,\n });\n },\n [setTextFieldState]\n );\n\n return {\n ...remaining,\n reset,\n value: number,\n setState,\n fieldProps: {\n ...fieldProps,\n min,\n max,\n step,\n type: \"number\",\n },\n };\n}\n"],"names":["useCallback","useRef","useState","withinRange","useTextField","noop","useNumberField","options","min","max","step","onBlur","onChange","updateValue","updateValueOnBlur","defaultValue","textOptions","number","setNumber","initial","value","_value","reset","resetTextField","fieldProps","setState","setTextFieldState","remaining","isNumber","event","isPropagationStopped","input","currentTarget","setCustomValidity","checkValidity","validity","badInput","valueAsNumber","current","Number","isNaN","undefined","valid","rangeUnderflow","rangeOverflow","nextState","prevNumber","nextNumber","prevState","updated","error","errorMessage","type"],"mappings":"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"}
@@ -69,35 +69,35 @@ export interface ProvidedRadioGroupProps<V extends string | number> {
69
69
  export type GetRadioGroupProps<V extends string | number> = (value: V) => Readonly<ProvidedRadioGroupProps<V>>;
70
70
  /** @since 6.0.0 */
71
71
  export interface RadioGroupImplementation<V extends string | number> {
72
- reset(): void;
72
+ reset: () => void;
73
73
  value: V;
74
74
  setValue: UseStateSetter<V>;
75
75
  getRadioProps: GetRadioGroupProps<V>;
76
76
  }
77
77
  export type GetMenuItemRadioGroupProps<V extends string | number> = (value: V) => Readonly<{
78
78
  checked: boolean;
79
- onCheckedChange(): void;
79
+ onCheckedChange: () => void;
80
80
  }>;
81
81
  /** @since 6.0.0 */
82
82
  export interface MenuItemRadioGroupImplementation<V extends string | number> {
83
- reset(): void;
83
+ reset: () => void;
84
84
  value: V;
85
85
  setValue: UseStateSetter<V>;
86
86
  getRadioProps: GetMenuItemRadioGroupProps<V>;
87
87
  }
88
88
  /** @since 6.0.0 */
89
89
  export interface CombinedRadioGroupReturnValue<V extends string | number> {
90
- reset(): void;
90
+ reset: () => void;
91
91
  value: V;
92
92
  setValue: UseStateSetter<V>;
93
- getRadioProps?(value: V): {
93
+ getRadioProps?: (value: V) => {
94
94
  name?: string;
95
95
  value?: V;
96
96
  checked: boolean;
97
97
  error?: boolean;
98
98
  required?: boolean;
99
99
  onChange?: ChangeEventHandler<HTMLInputElement>;
100
- onCheckedChange?(): void;
100
+ onCheckedChange?: () => void;
101
101
  onInvalid?: FormEventHandler<HTMLInputElement>;
102
102
  };
103
103
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/form/useRadioGroup.ts"],"sourcesContent":["\"use client\";\nimport {\n useCallback,\n useRef,\n useState,\n type ChangeEventHandler,\n type FormEventHandler,\n} from \"react\";\nimport { type UseStateInitializer, type UseStateSetter } from \"../types.js\";\n\nconst noop = (): void => {\n // do nothing\n};\n\n/** @since 6.0.0 */\nexport interface RadioGroupOptions<T extends string | number> {\n /**\n * A `name` to apply to all the radios within the group. This is required if\n * unless {@link menu} is set to `true`.\n */\n name?: string;\n\n /**\n * Set this to `true` if using the `MenuItemRadio` component instead of the\n * `Radio` so the correct props can be provided.\n *\n * @defaultValue `false`\n */\n menu?: boolean;\n\n /**\n * The value of a radio that should be checked by default. If you want to\n * force the user to select one of the radios, keep this as the empty string\n * or set it to a string or number that does not represent a valid radio\n * value.\n *\n * @defaultValue `\"\"`\n */\n defaultValue?: UseStateInitializer<T>;\n\n /**\n * Set this to `true` if one of the radios within the group must be checked before\n * a form can be submitted.\n *\n * This option is invalid and will be ignored if {@link menu} is `true`.\n *\n * @defaultValue `false`\n */\n required?: boolean;\n\n /**\n * If you need to prevent the default behavior in a radio group for some\n * reason, you can provide a custom `onChange` event handler and call\n * `event.stopPropagation()`. This will be called whenever a new radio button\n * is checked.\n *\n * This option is invalid and will be ignored if {@link menu} is `true`.\n *\n * @defaultValue `() => {}`\n */\n onChange?: ChangeEventHandler<HTMLInputElement>;\n\n /**\n * If the radio group has {@link required} set to `true`, the radios will gain\n * the `error` state if a form is submitted without a checked radio. If you\n * want to prevent that behavior for some reason, you can provide this\n * function and call `event.stopPropagation()`.\n *\n * This option is invalid and will be ignored if {@link menu} is `true`.\n *\n * @defaultValue `() => {}`\n */\n onInvalid?: FormEventHandler<HTMLInputElement>;\n}\n\n/** @since 6.0.0 */\nexport interface ProvidedRadioGroupProps<V extends string | number> {\n name: string;\n value: V;\n checked: boolean;\n onChange: ChangeEventHandler<HTMLInputElement>;\n error: boolean;\n required: boolean;\n onInvalid: FormEventHandler<HTMLInputElement>;\n}\n\n/** @since 6.0.0 */\nexport type GetRadioGroupProps<V extends string | number> = (\n value: V\n) => Readonly<ProvidedRadioGroupProps<V>>;\n\n/** @since 6.0.0 */\nexport interface RadioGroupImplementation<V extends string | number> {\n reset(): void;\n value: V;\n setValue: UseStateSetter<V>;\n getRadioProps: GetRadioGroupProps<V>;\n}\n\nexport type GetMenuItemRadioGroupProps<V extends string | number> = (\n value: V\n) => Readonly<{ checked: boolean; onCheckedChange(): void }>;\n\n/** @since 6.0.0 */\nexport interface MenuItemRadioGroupImplementation<V extends string | number> {\n reset(): void;\n value: V;\n setValue: UseStateSetter<V>;\n getRadioProps: GetMenuItemRadioGroupProps<V>;\n}\n\n/** @since 6.0.0 */\nexport interface CombinedRadioGroupReturnValue<V extends string | number> {\n reset(): void;\n value: V;\n setValue: UseStateSetter<V>;\n getRadioProps?(value: V): {\n name?: string;\n value?: V;\n checked: boolean;\n error?: boolean;\n required?: boolean;\n onChange?: ChangeEventHandler<HTMLInputElement>;\n onCheckedChange?(): void;\n onInvalid?: FormEventHandler<HTMLInputElement>;\n };\n}\n\n// Note: These overrides are set up so that the value will default to any\n// string.\n\n/**\n * @example Generic Number Example\n * ```tsx\n * const { value, getRadioProps } = useRadioGroup<number>({\n * name: \"group\",\n * defaultValue: -1\n * });\n *\n *\n * return (\n * <>\n * <Radio {...getRadioProps(0)} label=\"First\" />\n * <Radio {...getRadioProps(1)} label=\"Second\" />\n * <Radio {...getRadioProps(2)} label=\"Third\" />\n * </>\n * );\n * ```\n * @since 6.0.0\n */\nexport function useRadioGroup<V extends number>(\n options: RadioGroupOptions<V> & {\n menu?: false;\n name: string;\n defaultValue: UseStateInitializer<V>;\n }\n): RadioGroupImplementation<V>;\nexport function useRadioGroup<V extends number>(\n options: RadioGroupOptions<V> & {\n menu: true;\n name?: never;\n required?: never;\n onChange?: never;\n onInvalid?: never;\n defaultValue: UseStateInitializer<V>;\n }\n): MenuItemRadioGroupImplementation<V>;\n/**\n * @example Generic String Example\n * ```tsx\n * const { value, getRadioProps } = useRadioGroup({ name: \"group\" });\n *\n * return (\n * <>\n * <Radio {...getRadioProps(\"a\")} label=\"First\" />\n * <Radio {...getRadioProps(\"b\")} label=\"Second\" />\n * <Radio {...getRadioProps(\"c\")} label=\"Third\" />\n * </>\n * );\n * ```\n *\n * @example String Union Example\n * ```tsx\n * const values = [\n * { label: \"First\", value: \"a\" },\n * { label: \"Second\", value: \"b\" },\n * { label: \"Third\", value: \"c\" },\n * ] as const;\n *\n * type Values = typeof values[number][\"value\"];\n * // ^ \"a\" | \"b\" | \"c\"\n *\n * const { value, getRadioProps } = useRadioGroup<Values | \"\">({\n * name: \"group\",\n * defaultValue: \"\",\n * });\n *\n *\n * return (\n * <>\n * {values.map(({ label, value }) => (\n * <Radio {...getRadioProps(value)} key={value} label={label} />\n * ))}\n * </>\n * );\n * ```\n * @since 6.0.0\n */\nexport function useRadioGroup<V extends string>(\n options: RadioGroupOptions<V> & {\n menu?: false;\n name: string;\n defaultValue?: UseStateInitializer<V>;\n }\n): RadioGroupImplementation<V>;\nexport function useRadioGroup<V extends string>(\n options: RadioGroupOptions<V> & {\n menu: true;\n name?: never;\n required?: never;\n onChange?: never;\n onInvalid?: never;\n defaultValue?: UseStateInitializer<V>;\n }\n): MenuItemRadioGroupImplementation<V>;\n/**\n * @example Strict Union Example\n * ```tsx\n * type ValidValues = 1 | 2 | 3 | 4 | \"\" | \"a\" | \"b\";\n *\n * const { value, getRadioProps } = useRadioGroup<ValidValues>({\n * name: \"group\",\n * defaultValue: \"\"\n * });\n *\n *\n * return (\n * <>\n * <Radio {...getRadioProps(1)} label=\"First\" />\n * <Radio {...getRadioProps(2)} label=\"Second\" />\n * <Radio {...getRadioProps(3)} label=\"Third\" />\n * <Radio {...getRadioProps(4)} label=\"Forth\" />\n * <Radio {...getRadioProps(\"a\")} label=\"Fifth\" />\n * <Radio {...getRadioProps(\"b\")} label=\"Sixth\" />\n * <Radio {...getRadioProps(\"c\")} label=\"Seventh\" />\n * </>\n * );\n * ```\n * @since 6.0.0\n */\nexport function useRadioGroup<V extends string | number>(\n options: RadioGroupOptions<V>\n): CombinedRadioGroupReturnValue<V> {\n const {\n name,\n defaultValue,\n menu = false,\n required,\n onChange = noop,\n onInvalid = noop,\n } = options;\n const [value, setValue] = useState<V>(() => {\n if (typeof defaultValue === \"function\") {\n return defaultValue();\n }\n\n return defaultValue ?? (\"\" as V);\n });\n const initial = useRef(value);\n const [error, setError] = useState(false);\n\n return {\n reset: useCallback(() => {\n setError(false);\n setValue(initial.current);\n }, []),\n value,\n setValue,\n getRadioProps(radioValue) {\n const checked = value === radioValue;\n if (menu) {\n return {\n checked,\n onCheckedChange() {\n setValue(radioValue);\n },\n };\n }\n\n return {\n name,\n value: radioValue,\n error,\n checked,\n required,\n onChange(event) {\n onChange(event);\n setError(false);\n setValue(radioValue);\n },\n onInvalid(event) {\n onInvalid(event);\n setError(true);\n },\n };\n },\n };\n}\n"],"names":["useCallback","useRef","useState","noop","useRadioGroup","options","name","defaultValue","menu","required","onChange","onInvalid","value","setValue","initial","error","setError","reset","current","getRadioProps","radioValue","checked","onCheckedChange","event"],"mappings":"AAAA;AACA,SACEA,WAAW,EACXC,MAAM,EACNC,QAAQ,QAGH,QAAQ;AAGf,MAAMC,OAAO;AACX,aAAa;AACf;AAqNA;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASC,cACdC,OAA6B;IAE7B,MAAM,EACJC,IAAI,EACJC,YAAY,EACZC,OAAO,KAAK,EACZC,QAAQ,EACRC,WAAWP,IAAI,EACfQ,YAAYR,IAAI,EACjB,GAAGE;IACJ,MAAM,CAACO,OAAOC,SAAS,GAAGX,SAAY;QACpC,IAAI,OAAOK,iBAAiB,YAAY;YACtC,OAAOA;QACT;QAEA,OAAOA,gBAAiB;IAC1B;IACA,MAAMO,UAAUb,OAAOW;IACvB,MAAM,CAACG,OAAOC,SAAS,GAAGd,SAAS;IAEnC,OAAO;QACLe,OAAOjB,YAAY;YACjBgB,SAAS;YACTH,SAASC,QAAQI,OAAO;QAC1B,GAAG,EAAE;QACLN;QACAC;QACAM,eAAcC,UAAU;YACtB,MAAMC,UAAUT,UAAUQ;YAC1B,IAAIZ,MAAM;gBACR,OAAO;oBACLa;oBACAC;wBACET,SAASO;oBACX;gBACF;YACF;YAEA,OAAO;gBACLd;gBACAM,OAAOQ;gBACPL;gBACAM;gBACAZ;gBACAC,UAASa,KAAK;oBACZb,SAASa;oBACTP,SAAS;oBACTH,SAASO;gBACX;gBACAT,WAAUY,KAAK;oBACbZ,UAAUY;oBACVP,SAAS;gBACX;YACF;QACF;IACF;AACF"}
1
+ {"version":3,"sources":["../../src/form/useRadioGroup.ts"],"sourcesContent":["\"use client\";\nimport {\n useCallback,\n useRef,\n useState,\n type ChangeEventHandler,\n type FormEventHandler,\n} from \"react\";\nimport { type UseStateInitializer, type UseStateSetter } from \"../types.js\";\n\nconst noop = (): void => {\n // do nothing\n};\n\n/** @since 6.0.0 */\nexport interface RadioGroupOptions<T extends string | number> {\n /**\n * A `name` to apply to all the radios within the group. This is required if\n * unless {@link menu} is set to `true`.\n */\n name?: string;\n\n /**\n * Set this to `true` if using the `MenuItemRadio` component instead of the\n * `Radio` so the correct props can be provided.\n *\n * @defaultValue `false`\n */\n menu?: boolean;\n\n /**\n * The value of a radio that should be checked by default. If you want to\n * force the user to select one of the radios, keep this as the empty string\n * or set it to a string or number that does not represent a valid radio\n * value.\n *\n * @defaultValue `\"\"`\n */\n defaultValue?: UseStateInitializer<T>;\n\n /**\n * Set this to `true` if one of the radios within the group must be checked before\n * a form can be submitted.\n *\n * This option is invalid and will be ignored if {@link menu} is `true`.\n *\n * @defaultValue `false`\n */\n required?: boolean;\n\n /**\n * If you need to prevent the default behavior in a radio group for some\n * reason, you can provide a custom `onChange` event handler and call\n * `event.stopPropagation()`. This will be called whenever a new radio button\n * is checked.\n *\n * This option is invalid and will be ignored if {@link menu} is `true`.\n *\n * @defaultValue `() => {}`\n */\n onChange?: ChangeEventHandler<HTMLInputElement>;\n\n /**\n * If the radio group has {@link required} set to `true`, the radios will gain\n * the `error` state if a form is submitted without a checked radio. If you\n * want to prevent that behavior for some reason, you can provide this\n * function and call `event.stopPropagation()`.\n *\n * This option is invalid and will be ignored if {@link menu} is `true`.\n *\n * @defaultValue `() => {}`\n */\n onInvalid?: FormEventHandler<HTMLInputElement>;\n}\n\n/** @since 6.0.0 */\nexport interface ProvidedRadioGroupProps<V extends string | number> {\n name: string;\n value: V;\n checked: boolean;\n onChange: ChangeEventHandler<HTMLInputElement>;\n error: boolean;\n required: boolean;\n onInvalid: FormEventHandler<HTMLInputElement>;\n}\n\n/** @since 6.0.0 */\nexport type GetRadioGroupProps<V extends string | number> = (\n value: V\n) => Readonly<ProvidedRadioGroupProps<V>>;\n\n/** @since 6.0.0 */\nexport interface RadioGroupImplementation<V extends string | number> {\n reset: () => void;\n value: V;\n setValue: UseStateSetter<V>;\n getRadioProps: GetRadioGroupProps<V>;\n}\n\nexport type GetMenuItemRadioGroupProps<V extends string | number> = (\n value: V\n) => Readonly<{ checked: boolean; onCheckedChange: () => void }>;\n\n/** @since 6.0.0 */\nexport interface MenuItemRadioGroupImplementation<V extends string | number> {\n reset: () => void;\n value: V;\n setValue: UseStateSetter<V>;\n getRadioProps: GetMenuItemRadioGroupProps<V>;\n}\n\n/** @since 6.0.0 */\nexport interface CombinedRadioGroupReturnValue<V extends string | number> {\n reset: () => void;\n value: V;\n setValue: UseStateSetter<V>;\n getRadioProps?: (value: V) => {\n name?: string;\n value?: V;\n checked: boolean;\n error?: boolean;\n required?: boolean;\n onChange?: ChangeEventHandler<HTMLInputElement>;\n onCheckedChange?: () => void;\n onInvalid?: FormEventHandler<HTMLInputElement>;\n };\n}\n\n// Note: These overrides are set up so that the value will default to any\n// string.\n\n/**\n * @example Generic Number Example\n * ```tsx\n * const { value, getRadioProps } = useRadioGroup<number>({\n * name: \"group\",\n * defaultValue: -1\n * });\n *\n *\n * return (\n * <>\n * <Radio {...getRadioProps(0)} label=\"First\" />\n * <Radio {...getRadioProps(1)} label=\"Second\" />\n * <Radio {...getRadioProps(2)} label=\"Third\" />\n * </>\n * );\n * ```\n * @since 6.0.0\n */\nexport function useRadioGroup<V extends number>(\n options: RadioGroupOptions<V> & {\n menu?: false;\n name: string;\n defaultValue: UseStateInitializer<V>;\n }\n): RadioGroupImplementation<V>;\nexport function useRadioGroup<V extends number>(\n options: RadioGroupOptions<V> & {\n menu: true;\n name?: never;\n required?: never;\n onChange?: never;\n onInvalid?: never;\n defaultValue: UseStateInitializer<V>;\n }\n): MenuItemRadioGroupImplementation<V>;\n/**\n * @example Generic String Example\n * ```tsx\n * const { value, getRadioProps } = useRadioGroup({ name: \"group\" });\n *\n * return (\n * <>\n * <Radio {...getRadioProps(\"a\")} label=\"First\" />\n * <Radio {...getRadioProps(\"b\")} label=\"Second\" />\n * <Radio {...getRadioProps(\"c\")} label=\"Third\" />\n * </>\n * );\n * ```\n *\n * @example String Union Example\n * ```tsx\n * const values = [\n * { label: \"First\", value: \"a\" },\n * { label: \"Second\", value: \"b\" },\n * { label: \"Third\", value: \"c\" },\n * ] as const;\n *\n * type Values = typeof values[number][\"value\"];\n * // ^ \"a\" | \"b\" | \"c\"\n *\n * const { value, getRadioProps } = useRadioGroup<Values | \"\">({\n * name: \"group\",\n * defaultValue: \"\",\n * });\n *\n *\n * return (\n * <>\n * {values.map(({ label, value }) => (\n * <Radio {...getRadioProps(value)} key={value} label={label} />\n * ))}\n * </>\n * );\n * ```\n * @since 6.0.0\n */\nexport function useRadioGroup<V extends string>(\n options: RadioGroupOptions<V> & {\n menu?: false;\n name: string;\n defaultValue?: UseStateInitializer<V>;\n }\n): RadioGroupImplementation<V>;\nexport function useRadioGroup<V extends string>(\n options: RadioGroupOptions<V> & {\n menu: true;\n name?: never;\n required?: never;\n onChange?: never;\n onInvalid?: never;\n defaultValue?: UseStateInitializer<V>;\n }\n): MenuItemRadioGroupImplementation<V>;\n/**\n * @example Strict Union Example\n * ```tsx\n * type ValidValues = 1 | 2 | 3 | 4 | \"\" | \"a\" | \"b\";\n *\n * const { value, getRadioProps } = useRadioGroup<ValidValues>({\n * name: \"group\",\n * defaultValue: \"\"\n * });\n *\n *\n * return (\n * <>\n * <Radio {...getRadioProps(1)} label=\"First\" />\n * <Radio {...getRadioProps(2)} label=\"Second\" />\n * <Radio {...getRadioProps(3)} label=\"Third\" />\n * <Radio {...getRadioProps(4)} label=\"Forth\" />\n * <Radio {...getRadioProps(\"a\")} label=\"Fifth\" />\n * <Radio {...getRadioProps(\"b\")} label=\"Sixth\" />\n * <Radio {...getRadioProps(\"c\")} label=\"Seventh\" />\n * </>\n * );\n * ```\n * @since 6.0.0\n */\nexport function useRadioGroup<V extends string | number>(\n options: RadioGroupOptions<V>\n): CombinedRadioGroupReturnValue<V> {\n const {\n name,\n defaultValue,\n menu = false,\n required,\n onChange = noop,\n onInvalid = noop,\n } = options;\n const [value, setValue] = useState<V>(() => {\n if (typeof defaultValue === \"function\") {\n return defaultValue();\n }\n\n return defaultValue ?? (\"\" as V);\n });\n const initial = useRef(value);\n const [error, setError] = useState(false);\n\n return {\n reset: useCallback(() => {\n setError(false);\n setValue(initial.current);\n }, []),\n value,\n setValue,\n getRadioProps(radioValue) {\n const checked = value === radioValue;\n if (menu) {\n return {\n checked,\n onCheckedChange() {\n setValue(radioValue);\n },\n };\n }\n\n return {\n name,\n value: radioValue,\n error,\n checked,\n required,\n onChange(event) {\n onChange(event);\n setError(false);\n setValue(radioValue);\n },\n onInvalid(event) {\n onInvalid(event);\n setError(true);\n },\n };\n },\n };\n}\n"],"names":["useCallback","useRef","useState","noop","useRadioGroup","options","name","defaultValue","menu","required","onChange","onInvalid","value","setValue","initial","error","setError","reset","current","getRadioProps","radioValue","checked","onCheckedChange","event"],"mappings":"AAAA;AACA,SACEA,WAAW,EACXC,MAAM,EACNC,QAAQ,QAGH,QAAQ;AAGf,MAAMC,OAAO;AACX,aAAa;AACf;AAqNA;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASC,cACdC,OAA6B;IAE7B,MAAM,EACJC,IAAI,EACJC,YAAY,EACZC,OAAO,KAAK,EACZC,QAAQ,EACRC,WAAWP,IAAI,EACfQ,YAAYR,IAAI,EACjB,GAAGE;IACJ,MAAM,CAACO,OAAOC,SAAS,GAAGX,SAAY;QACpC,IAAI,OAAOK,iBAAiB,YAAY;YACtC,OAAOA;QACT;QAEA,OAAOA,gBAAiB;IAC1B;IACA,MAAMO,UAAUb,OAAOW;IACvB,MAAM,CAACG,OAAOC,SAAS,GAAGd,SAAS;IAEnC,OAAO;QACLe,OAAOjB,YAAY;YACjBgB,SAAS;YACTH,SAASC,QAAQI,OAAO;QAC1B,GAAG,EAAE;QACLN;QACAC;QACAM,eAAcC,UAAU;YACtB,MAAMC,UAAUT,UAAUQ;YAC1B,IAAIZ,MAAM;gBACR,OAAO;oBACLa;oBACAC;wBACET,SAASO;oBACX;gBACF;YACF;YAEA,OAAO;gBACLd;gBACAM,OAAOQ;gBACPL;gBACAM;gBACAZ;gBACAC,UAASa,KAAK;oBACZb,SAASa;oBACTP,SAAS;oBACTH,SAASO;gBACX;gBACAT,WAAUY,KAAK;oBACbZ,UAAUY;oBACVP,SAAS;gBACX;YACF;QACF;IACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/form/useResizingTextArea.ts"],"sourcesContent":["\"use client\";\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ChangeEventHandler,\n type Ref,\n type RefCallback,\n} from \"react\";\nimport { useEnsuredRef } from \"../useEnsuredRef.js\";\nimport { useResizeObserver } from \"../useResizeObserver.js\";\n\n// this is the default of 1.5rem line-height in the styles\nconst DEFAULT_LINE_HEIGHT = 24;\n\nconst noop = (): void => {\n // do nothing\n};\n\n/**\n * A textarea is normally resizable in browsers by default by dragging the\n * bottom right corner to the desired size which will set inline styles for\n * `height` and `width`. Since this makes creating layouts a bit more difficult,\n * this is disabled by default but can be configured using one of these values:\n *\n * - `\"auto\"` - The textarea will automatically grow in in height as the user\n * types until a max number of rows have been added. If there is additional\n * text, a scrollbar will appear in the textarea. The browser's native resize\n * behavior is disabled.\n * - `\"none\"` - The textarea's height and width will remain static\n * - `\"horizontal\"` - The textarea's width can be resized by the browser's\n * native resize behavior.\n * - `\"vertical\"` - The textarea's height can be resized by the browser's native\n * resize behavior.\n * - `\"both\"` - The browser's native resize behavior will be allowed.\n */\nexport type TextAreaResize =\n | \"none\"\n | \"auto\"\n | \"horizontal\"\n | \"vertical\"\n | \"both\";\n\n/** @internal */\nexport interface ResizingTextAreaOptions {\n resize: TextAreaResize;\n maxRows: number;\n onChange: ChangeEventHandler<HTMLTextAreaElement> | undefined;\n containerRef?: Ref<HTMLDivElement>;\n disableTransition: boolean | undefined;\n}\n\n/** @internal */\nexport interface ResizingTextAreaReturnValue {\n height: string | undefined;\n maskRef: RefCallback<HTMLTextAreaElement>;\n containerRef: RefCallback<HTMLDivElement>;\n onChange: ChangeEventHandler<HTMLTextAreaElement>;\n scrollable: boolean;\n disableTransition: boolean;\n}\n\n/** @internal */\nexport function useResizingTextArea(\n options: ResizingTextAreaOptions\n): ResizingTextAreaReturnValue {\n const {\n maxRows,\n resize,\n onChange = noop,\n containerRef: propContainerRef,\n disableTransition,\n } = options;\n\n const maskRef = useRef<HTMLTextAreaElement>(null);\n const [containerRef, containerRefCallback] = useEnsuredRef(propContainerRef);\n const [height, setHeight] = useState<number>();\n useEffect(() => {\n if (resize !== \"auto\") {\n setHeight(undefined);\n }\n }, [resize]);\n\n // Since access to the DOM is required to calculate the current height of the\n // textarea, do not enable the height transition until it has been calculated\n // once.\n const isHeightSet = useRef(true);\n useEffect(() => {\n isHeightSet.current = !height;\n }, [height]);\n\n // Do not enable the scrollbar until the max height has been reached since\n // it'll flash as the user types on OS that display scrollbars.\n //\n // Note: This does cause an infinite loop issue on browsers that display OS\n // when rendered in a flex/grid container and a \"fluid\" width since:\n // - the width changes when the overflow changes to `auto`\n // - the resize observer triggers since there was a width change\n // - the number of rows imght change because of this width change\n // - it might no longer be at the max height, so remove the scrollbar\n // - restart\n const [isMaxHeightReached, setMaxHeightReached] = useState(false);\n const updateHeight = useCallback(() => {\n const mask = maskRef.current;\n const container = containerRef.current;\n /* c8 ignore start */\n if (!mask || !container) {\n return;\n }\n /* c8 ignore stop */\n\n const containerStyles = window.getComputedStyle(container);\n const isBorderBox = containerStyles.boxSizing === \"border-box\";\n let borderHeight = 0;\n if (isBorderBox) {\n borderHeight =\n parseFloat(containerStyles.borderTopWidth) +\n parseFloat(containerStyles.borderBottomWidth);\n }\n\n let nextHeight = mask.scrollHeight + borderHeight;\n if (maxRows > 0) {\n nextHeight -= borderHeight;\n const maskStyles = window.getComputedStyle(mask);\n // in tests, this is `\"normal\"` by default instead of a number\n let lineHeight = parseFloat(maskStyles.lineHeight);\n if (Number.isNaN(lineHeight)) {\n lineHeight = DEFAULT_LINE_HEIGHT;\n }\n\n const maxHeight = maxRows * lineHeight;\n nextHeight = Math.min(maxHeight, nextHeight);\n setMaxHeightReached(nextHeight === maxHeight);\n nextHeight += borderHeight;\n }\n\n // This just makes snapshots look nicer since `nextHeight` will be 0 in\n // tests unless the user mocks out all the DOM properties\n if (nextHeight) {\n setHeight(nextHeight);\n }\n }, [containerRef, maxRows]);\n\n const maskRefCallback = useResizeObserver({\n ref: maskRef,\n onUpdate: updateHeight,\n disableHeight: true,\n });\n\n return {\n height: typeof height === \"number\" ? `${height}px` : undefined,\n maskRef: maskRefCallback,\n containerRef: containerRefCallback,\n scrollable: maxRows > 0 && isMaxHeightReached,\n disableTransition: disableTransition || isHeightSet.current,\n onChange(event) {\n onChange(event);\n\n const mask = maskRef.current;\n if (!mask || resize !== \"auto\") {\n return;\n }\n\n // to get the height transition to work, you have to set the height on:\n // - the main container element (including padding) that has the height\n // transition enabled\n // - a child div wrapper (without padding) that has the height transition\n // enabled\n // - the textarea element (without padding) and without a height transition\n //\n // if it isn't done this way, the height transition will look weird since\n // the text will be fixed to the bottom of the area and more text at the top\n // will become visible as the height transition completes. applying the\n // transition on the two parent elements work because:\n // - the height is set immediately on the text field so it expands to show all\n // the text\n // - the height is correctly applied to both parent elements, but their height\n // haven't fully been adjusted due to the animation\n // - the parent divs have overflow visible by default, so the textarea's text\n // will expand past the boundaries of the divs and not cause the upwards\n // animation weirdness.\n mask.value = event.currentTarget.value;\n updateHeight();\n },\n };\n}\n"],"names":["useCallback","useEffect","useRef","useState","useEnsuredRef","useResizeObserver","DEFAULT_LINE_HEIGHT","noop","useResizingTextArea","options","maxRows","resize","onChange","containerRef","propContainerRef","disableTransition","maskRef","containerRefCallback","height","setHeight","undefined","isHeightSet","current","isMaxHeightReached","setMaxHeightReached","updateHeight","mask","container","containerStyles","window","getComputedStyle","isBorderBox","boxSizing","borderHeight","parseFloat","borderTopWidth","borderBottomWidth","nextHeight","scrollHeight","maskStyles","lineHeight","Number","isNaN","maxHeight","Math","min","maskRefCallback","ref","onUpdate","disableHeight","scrollable","event","value","currentTarget"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/form/useResizingTextArea.ts"],"sourcesContent":["\"use client\";\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ChangeEventHandler,\n type Ref,\n type RefCallback,\n} from \"react\";\nimport { useEnsuredRef } from \"../useEnsuredRef.js\";\nimport { useResizeObserver } from \"../useResizeObserver.js\";\n\n// this is the default of 1.5rem line-height in the styles\nconst DEFAULT_LINE_HEIGHT = 24;\n\nconst noop = (): void => {\n // do nothing\n};\n\n/**\n * A textarea is normally resizable in browsers by default by dragging the\n * bottom right corner to the desired size which will set inline styles for\n * `height` and `width`. Since this makes creating layouts a bit more difficult,\n * this is disabled by default but can be configured using one of these values:\n *\n * - `\"auto\"` - The textarea will automatically grow in in height as the user\n * types until a max number of rows have been added. If there is additional\n * text, a scrollbar will appear in the textarea. The browser's native resize\n * behavior is disabled.\n * - `\"none\"` - The textarea's height and width will remain static\n * - `\"horizontal\"` - The textarea's width can be resized by the browser's\n * native resize behavior.\n * - `\"vertical\"` - The textarea's height can be resized by the browser's native\n * resize behavior.\n * - `\"both\"` - The browser's native resize behavior will be allowed.\n */\nexport type TextAreaResize =\n | \"none\"\n | \"auto\"\n | \"horizontal\"\n | \"vertical\"\n | \"both\";\n\n/** @internal */\nexport interface ResizingTextAreaOptions {\n resize: TextAreaResize;\n maxRows: number;\n onChange: ChangeEventHandler<HTMLTextAreaElement> | undefined;\n containerRef?: Ref<HTMLDivElement>;\n disableTransition: boolean | undefined;\n}\n\n/** @internal */\nexport interface ResizingTextAreaReturnValue {\n height: string | undefined;\n maskRef: RefCallback<HTMLTextAreaElement>;\n containerRef: RefCallback<HTMLDivElement>;\n onChange: ChangeEventHandler<HTMLTextAreaElement>;\n scrollable: boolean;\n disableTransition: boolean;\n}\n\n/** @internal */\nexport function useResizingTextArea(\n options: ResizingTextAreaOptions\n): ResizingTextAreaReturnValue {\n const {\n maxRows,\n resize,\n onChange = noop,\n containerRef: propContainerRef,\n disableTransition,\n } = options;\n\n const maskRef = useRef<HTMLTextAreaElement>(null);\n const [containerRef, containerRefCallback] = useEnsuredRef(propContainerRef);\n const [height, setHeight] = useState<number>();\n useEffect(() => {\n if (resize !== \"auto\") {\n setHeight(undefined);\n }\n }, [resize]);\n\n // Since access to the DOM is required to calculate the current height of the\n // textarea, do not enable the height transition until it has been calculated\n // once.\n const isHeightSet = useRef(true);\n useEffect(() => {\n isHeightSet.current = !height;\n }, [height]);\n\n // Do not enable the scrollbar until the max height has been reached since\n // it'll flash as the user types on OS that display scrollbars.\n //\n // Note: This does cause an infinite loop issue on browsers that display OS\n // when rendered in a flex/grid container and a \"fluid\" width since:\n // - the width changes when the overflow changes to `auto`\n // - the resize observer triggers since there was a width change\n // - the number of rows imght change because of this width change\n // - it might no longer be at the max height, so remove the scrollbar\n // - restart\n const [isMaxHeightReached, setMaxHeightReached] = useState(false);\n const updateHeight = useCallback(() => {\n const mask = maskRef.current;\n const container = containerRef.current;\n /* c8 ignore start */\n if (!mask || !container) {\n return;\n }\n /* c8 ignore stop */\n\n const containerStyles = window.getComputedStyle(container);\n const isBorderBox = containerStyles.boxSizing === \"border-box\";\n let borderHeight = 0;\n if (isBorderBox) {\n borderHeight =\n parseFloat(containerStyles.borderTopWidth) +\n parseFloat(containerStyles.borderBottomWidth);\n }\n\n let nextHeight = mask.scrollHeight + borderHeight;\n if (maxRows > 0) {\n nextHeight -= borderHeight;\n const maskStyles = window.getComputedStyle(mask);\n // in tests, this is `\"normal\"` by default instead of a number\n let lineHeight = parseFloat(maskStyles.lineHeight);\n if (Number.isNaN(lineHeight)) {\n lineHeight = DEFAULT_LINE_HEIGHT;\n }\n\n const maxHeight = maxRows * lineHeight;\n nextHeight = Math.min(maxHeight, nextHeight);\n setMaxHeightReached(nextHeight === maxHeight);\n nextHeight += borderHeight;\n }\n\n // This just makes snapshots look nicer since `nextHeight` will be 0 in\n // tests unless the user mocks out all the DOM properties\n if (nextHeight) {\n setHeight(nextHeight);\n }\n }, [containerRef, maxRows]);\n\n const maskRefCallback = useResizeObserver({\n ref: maskRef,\n onUpdate: updateHeight,\n disableHeight: true,\n });\n\n return {\n height: typeof height === \"number\" ? `${height}px` : undefined,\n maskRef: maskRefCallback,\n containerRef: containerRefCallback,\n scrollable: maxRows > 0 && isMaxHeightReached,\n disableTransition: disableTransition || isHeightSet.current,\n onChange(event) {\n onChange(event);\n\n const mask = maskRef.current;\n if (!mask || resize !== \"auto\") {\n return;\n }\n\n // to get the height transition to work, you have to set the height on:\n // - the main container element (including padding) that has the height\n // transition enabled\n // - a child div wrapper (without padding) that has the height transition\n // enabled\n // - the textarea element (without padding) and without a height transition\n //\n // if it isn't done this way, the height transition will look weird since\n // the text will be fixed to the bottom of the area and more text at the top\n // will become visible as the height transition completes. applying the\n // transition on the two parent elements work because:\n // - the height is set immediately on the text field so it expands to show all\n // the text\n // - the height is correctly applied to both parent elements, but their height\n // haven't fully been adjusted due to the animation\n // - the parent divs have overflow visible by default, so the textarea's text\n // will expand past the boundaries of the divs and not cause the upwards\n // animation weirdness.\n mask.value = event.currentTarget.value;\n updateHeight();\n },\n };\n}\n"],"names":["useCallback","useEffect","useRef","useState","useEnsuredRef","useResizeObserver","DEFAULT_LINE_HEIGHT","noop","useResizingTextArea","options","maxRows","resize","onChange","containerRef","propContainerRef","disableTransition","maskRef","containerRefCallback","height","setHeight","undefined","isHeightSet","current","isMaxHeightReached","setMaxHeightReached","updateHeight","mask","container","containerStyles","window","getComputedStyle","isBorderBox","boxSizing","borderHeight","parseFloat","borderTopWidth","borderBottomWidth","nextHeight","scrollHeight","maskStyles","lineHeight","Number","isNaN","maxHeight","Math","min","maskRefCallback","ref","onUpdate","disableHeight","scrollable","event","value","currentTarget"],"mappings":"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"}
@@ -1,16 +1,15 @@
1
- import { type BaseComboboxOptions, type ComboboxImplementation } from "./useCombobox.js";
1
+ import { type ComboboxImplementation, type ConfigurableComboboxOptions } from "./useCombobox.js";
2
2
  /**
3
3
  * @since 6.0.0
4
4
  */
5
- export interface SelectComboboxOptions<ComboboxEl extends HTMLElement = HTMLInputElement, PopupEl extends HTMLElement = HTMLElement> extends BaseComboboxOptions<ComboboxEl, PopupEl> {
5
+ export interface SelectComboboxOptions<ComboboxEl extends HTMLElement = HTMLInputElement, PopupEl extends HTMLElement = HTMLElement> extends ConfigurableComboboxOptions<ComboboxEl, PopupEl> {
6
6
  value: string;
7
7
  values: readonly string[];
8
8
  }
9
9
  /**
10
10
  * @since 6.0.0
11
11
  */
12
- export interface SelectComboboxImplementation<ComboboxEl extends HTMLElement = HTMLInputElement, PopupEl extends HTMLElement = HTMLElement> extends ComboboxImplementation<ComboboxEl, PopupEl> {
13
- }
12
+ export type SelectComboboxImplementation<ComboboxEl extends HTMLElement = HTMLInputElement, PopupEl extends HTMLElement = HTMLElement> = ComboboxImplementation<ComboboxEl, PopupEl>;
14
13
  /**
15
14
  * @since 6.0.0
16
15
  */
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/form/useSelectCombobox.ts"],"sourcesContent":["\"use client\";\nimport {\n useCombobox,\n type BaseComboboxOptions,\n type ComboboxImplementation,\n} from \"./useCombobox.js\";\n\n/**\n * @since 6.0.0\n */\nexport interface SelectComboboxOptions<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends BaseComboboxOptions<ComboboxEl, PopupEl> {\n value: string;\n values: readonly string[];\n}\n\n/**\n * @since 6.0.0\n */\nexport interface SelectComboboxImplementation<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends ComboboxImplementation<ComboboxEl, PopupEl> {}\n\n/**\n * @since 6.0.0\n */\nexport function useSelectCombobox<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n>(\n options: SelectComboboxOptions<ComboboxEl, PopupEl>\n): SelectComboboxImplementation<ComboboxEl, PopupEl> {\n const { value, values, ...comboboxOptions } = options;\n\n return useCombobox({\n ...comboboxOptions,\n searchable: true,\n extendKeyDown(movementData) {\n const { event, show, focusLast, visible } = movementData;\n if (visible) {\n return;\n }\n\n switch (event.key) {\n case \" \":\n case \"Home\":\n case \"End\":\n event.preventDefault();\n event.stopPropagation();\n focusLast.current = event.key === \"End\";\n show();\n break;\n }\n },\n getEnterDefaultFocusedIndex(options) {\n const { focusLast } = options;\n if (focusLast && !value) {\n return values.length - 1;\n }\n\n return Math.max(\n 0,\n values.findIndex((option) => option === value)\n );\n },\n });\n}\n"],"names":["useCombobox","useSelectCombobox","options","value","values","comboboxOptions","searchable","extendKeyDown","movementData","event","show","focusLast","visible","key","preventDefault","stopPropagation","current","getEnterDefaultFocusedIndex","length","Math","max","findIndex","option"],"mappings":"AAAA;AACA,SACEA,WAAW,QAGN,mBAAmB;AAqB1B;;CAEC,GACD,OAAO,SAASC,kBAIdC,OAAmD;IAEnD,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAE,GAAGC,iBAAiB,GAAGH;IAE9C,OAAOF,YAAY;QACjB,GAAGK,eAAe;QAClBC,YAAY;QACZC,eAAcC,YAAY;YACxB,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAEC,SAAS,EAAEC,OAAO,EAAE,GAAGJ;YAC5C,IAAII,SAAS;gBACX;YACF;YAEA,OAAQH,MAAMI,GAAG;gBACf,KAAK;gBACL,KAAK;gBACL,KAAK;oBACHJ,MAAMK,cAAc;oBACpBL,MAAMM,eAAe;oBACrBJ,UAAUK,OAAO,GAAGP,MAAMI,GAAG,KAAK;oBAClCH;oBACA;YACJ;QACF;QACAO,6BAA4Bf,OAAO;YACjC,MAAM,EAAES,SAAS,EAAE,GAAGT;YACtB,IAAIS,aAAa,CAACR,OAAO;gBACvB,OAAOC,OAAOc,MAAM,GAAG;YACzB;YAEA,OAAOC,KAAKC,GAAG,CACb,GACAhB,OAAOiB,SAAS,CAAC,CAACC,SAAWA,WAAWnB;QAE5C;IACF;AACF"}
1
+ {"version":3,"sources":["../../src/form/useSelectCombobox.ts"],"sourcesContent":["\"use client\";\nimport {\n useCombobox,\n type ComboboxImplementation,\n type ConfigurableComboboxOptions,\n} from \"./useCombobox.js\";\n\n/**\n * @since 6.0.0\n */\nexport interface SelectComboboxOptions<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> extends ConfigurableComboboxOptions<ComboboxEl, PopupEl> {\n value: string;\n values: readonly string[];\n}\n\n/**\n * @since 6.0.0\n */\nexport type SelectComboboxImplementation<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n> = ComboboxImplementation<ComboboxEl, PopupEl>;\n\n/**\n * @since 6.0.0\n */\nexport function useSelectCombobox<\n ComboboxEl extends HTMLElement = HTMLInputElement,\n PopupEl extends HTMLElement = HTMLElement,\n>(\n options: SelectComboboxOptions<ComboboxEl, PopupEl>\n): SelectComboboxImplementation<ComboboxEl, PopupEl> {\n const { value, values, ...comboboxOptions } = options;\n\n return useCombobox({\n ...comboboxOptions,\n searchable: true,\n extendKeyDown(movementData) {\n const { event, show, focusLast, visible } = movementData;\n if (visible) {\n return;\n }\n\n switch (event.key) {\n case \" \":\n case \"Home\":\n case \"End\":\n event.preventDefault();\n event.stopPropagation();\n focusLast.current = event.key === \"End\";\n show();\n break;\n }\n },\n getEnterDefaultFocusedIndex(options) {\n const { focusLast } = options;\n if (focusLast && !value) {\n return values.length - 1;\n }\n\n return Math.max(\n 0,\n values.findIndex((option) => option === value)\n );\n },\n });\n}\n"],"names":["useCombobox","useSelectCombobox","options","value","values","comboboxOptions","searchable","extendKeyDown","movementData","event","show","focusLast","visible","key","preventDefault","stopPropagation","current","getEnterDefaultFocusedIndex","length","Math","max","findIndex","option"],"mappings":"AAAA;AACA,SACEA,WAAW,QAGN,mBAAmB;AAqB1B;;CAEC,GACD,OAAO,SAASC,kBAIdC,OAAmD;IAEnD,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAE,GAAGC,iBAAiB,GAAGH;IAE9C,OAAOF,YAAY;QACjB,GAAGK,eAAe;QAClBC,YAAY;QACZC,eAAcC,YAAY;YACxB,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAEC,SAAS,EAAEC,OAAO,EAAE,GAAGJ;YAC5C,IAAII,SAAS;gBACX;YACF;YAEA,OAAQH,MAAMI,GAAG;gBACf,KAAK;gBACL,KAAK;gBACL,KAAK;oBACHJ,MAAMK,cAAc;oBACpBL,MAAMM,eAAe;oBACrBJ,UAAUK,OAAO,GAAGP,MAAMI,GAAG,KAAK;oBAClCH;oBACA;YACJ;QACF;QACAO,6BAA4Bf,OAAO;YACjC,MAAM,EAAES,SAAS,EAAE,GAAGT;YACtB,IAAIS,aAAa,CAACR,OAAO;gBACvB,OAAOC,OAAOc,MAAM,GAAG;YACzB;YAEA,OAAOC,KAAKC,GAAG,CACb,GACAhB,OAAOiB,SAAS,CAAC,CAACC,SAAWA,WAAWnB;QAE5C;IACF;AACF"}
@@ -239,7 +239,7 @@ export interface TextFieldHookOptions<E extends HTMLInputElement | HTMLTextAreaE
239
239
  /** @since 6.0.0 */
240
240
  export interface TextFieldImplementation<E extends HTMLInputElement | HTMLTextAreaElement> extends TextFieldHookState {
241
241
  fieldRef: RefObject<E>;
242
- reset(): void;
242
+ reset: () => void;
243
243
  setState: UseStateSetter<Readonly<TextFieldHookState>>;
244
244
  fieldProps: ProvidedTextFieldProps<E>;
245
245
  }