@carbon/react 1.90.0-rc.0 → 1.91.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +923 -964
  2. package/es/components/AILabel/index.js +8 -6
  3. package/es/components/Breadcrumb/BreadcrumbItem.js +2 -0
  4. package/es/components/Button/Button.js +3 -0
  5. package/es/components/ChatButton/ChatButton.js +1 -0
  6. package/es/components/CheckboxGroup/CheckboxGroup.js +21 -2
  7. package/es/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  8. package/es/components/CodeSnippet/CodeSnippet.js +1 -1
  9. package/es/components/ComboBox/ComboBox.js +18 -13
  10. package/es/components/ComboButton/index.js +2 -1
  11. package/es/components/ComposedModal/ComposedModal.js +5 -2
  12. package/es/components/Copy/Copy.d.ts +1 -1
  13. package/es/components/Copy/Copy.js +1 -1
  14. package/es/components/CopyButton/CopyButton.d.ts +1 -1
  15. package/es/components/CopyButton/CopyButton.js +1 -1
  16. package/es/components/DataTable/DataTable.d.ts +60 -15
  17. package/es/components/DataTable/DataTable.js +119 -178
  18. package/es/components/DataTable/Table.d.ts +2 -2
  19. package/es/components/DataTable/Table.js +4 -4
  20. package/es/components/DataTable/TableExpandHeader.d.ts +1 -1
  21. package/es/components/DataTable/TableExpandHeader.js +6 -2
  22. package/es/components/DataTable/TableExpandRow.js +1 -0
  23. package/es/components/DataTable/TableHeader.js +2 -0
  24. package/es/components/DataTable/TableRow.js +5 -0
  25. package/es/components/DataTable/TableSlugRow.js +1 -0
  26. package/es/components/DataTable/TableToolbarMenu.js +3 -0
  27. package/es/components/DataTable/state/sorting.d.ts +3 -1
  28. package/es/components/DataTable/state/sorting.js +2 -0
  29. package/es/components/DataTable/tools/sorting.js +1 -0
  30. package/es/components/DatePicker/DatePicker.d.ts +0 -12
  31. package/es/components/DatePicker/DatePicker.js +17 -6
  32. package/es/components/DatePicker/plugins/rangePlugin.d.ts +19 -2
  33. package/es/components/DatePicker/plugins/rangePlugin.js +18 -14
  34. package/es/components/DatePickerInput/DatePickerInput.js +6 -0
  35. package/es/components/Dialog/Dialog.js +10 -2
  36. package/es/components/Dropdown/Dropdown.js +17 -16
  37. package/es/components/ErrorBoundary/ErrorBoundaryContext.js +1 -0
  38. package/es/components/FeatureFlags/index.js +1 -0
  39. package/es/components/FileUploader/FileUploader.js +9 -2
  40. package/es/components/FileUploader/FileUploaderButton.js +1 -1
  41. package/es/components/FileUploader/FileUploaderDropContainer.js +1 -1
  42. package/es/components/FileUploader/FileUploaderItem.js +3 -0
  43. package/es/components/FluidMultiSelect/FluidMultiSelect.js +2 -0
  44. package/es/components/FluidNumberInput/FluidNumberInput.js +3 -2
  45. package/es/components/FluidSearch/FluidSearch.js +3 -2
  46. package/es/components/FluidSelect/FluidSelect.js +3 -2
  47. package/es/components/FluidTextInput/FluidTextInput.js +3 -2
  48. package/es/components/FluidTimePicker/FluidTimePicker.js +11 -4
  49. package/es/components/FluidTimePickerSelect/FluidTimePickerSelect.js +3 -2
  50. package/es/components/Grid/CSSGrid.js +5 -0
  51. package/es/components/Grid/Column.js +3 -0
  52. package/es/components/Grid/ColumnHang.js +1 -0
  53. package/es/components/Grid/FlexGrid.js +1 -0
  54. package/es/components/Grid/Row.js +1 -0
  55. package/es/components/Heading/index.js +3 -1
  56. package/es/components/IconButton/index.js +5 -3
  57. package/es/components/IconIndicator/index.js +4 -2
  58. package/es/components/InlineCheckbox/InlineCheckbox.js +3 -2
  59. package/es/components/Layout/index.js +6 -4
  60. package/es/components/LayoutDirection/LayoutDirection.js +2 -0
  61. package/es/components/Link/Link.js +3 -0
  62. package/es/components/ListBox/ListBoxMenuItem.js +4 -1
  63. package/es/components/ListBox/next/ListBoxTrigger.js +3 -2
  64. package/es/components/Menu/Menu.js +6 -9
  65. package/es/components/Menu/MenuContext.js +1 -0
  66. package/es/components/Menu/MenuItem.d.ts +1 -1
  67. package/es/components/Menu/MenuItem.js +10 -18
  68. package/es/components/MenuButton/index.js +7 -2
  69. package/es/components/Modal/Modal.js +4 -1
  70. package/es/components/ModalWrapper/ModalWrapper.js +2 -0
  71. package/es/components/MultiSelect/FilterableMultiSelect.js +25 -6
  72. package/es/components/MultiSelect/MultiSelect.js +22 -17
  73. package/es/components/Notification/Notification.d.ts +6 -6
  74. package/es/components/Notification/Notification.js +7 -7
  75. package/es/components/NumberInput/NumberInput.js +7 -1
  76. package/es/components/OverflowMenu/OverflowMenu.js +3 -1
  77. package/es/components/OverflowMenu/next/index.js +4 -3
  78. package/es/components/OverflowMenuItem/OverflowMenuItem.js +2 -0
  79. package/es/components/PageHeader/PageHeader.d.ts +3 -3
  80. package/es/components/PageHeader/PageHeader.js +22 -8
  81. package/es/components/Pagination/Pagination.js +6 -2
  82. package/es/components/PaginationNav/PaginationNav.js +2 -5
  83. package/es/components/Popover/index.js +15 -5
  84. package/es/components/ProgressBar/ProgressBar.js +4 -2
  85. package/es/components/RadioTile/RadioTile.js +2 -2
  86. package/es/components/Search/Search.d.ts +4 -2
  87. package/es/components/Search/Search.js +7 -6
  88. package/es/components/Select/Select.js +2 -3
  89. package/es/components/ShapeIndicator/index.js +4 -2
  90. package/es/components/SkeletonPlaceholder/SkeletonPlaceholder.d.ts +4 -4
  91. package/es/components/SkeletonPlaceholder/SkeletonPlaceholder.js +1 -2
  92. package/es/components/SkeletonText/SkeletonText.js +0 -2
  93. package/es/components/Slider/Slider.d.ts +144 -188
  94. package/es/components/Slider/Slider.js +798 -726
  95. package/es/components/Slider/index.d.ts +2 -2
  96. package/es/components/Stack/HStack.js +1 -0
  97. package/es/components/Stack/Stack.js +6 -9
  98. package/es/components/Stack/VStack.js +1 -0
  99. package/es/components/StructuredList/StructuredList.js +3 -0
  100. package/es/components/Switch/Switch.js +1 -1
  101. package/es/components/Tabs/Tabs.d.ts +4 -0
  102. package/es/components/Tabs/Tabs.js +28 -17
  103. package/es/components/Tag/DismissibleTag.js +2 -0
  104. package/es/components/Tag/OperationalTag.js +2 -0
  105. package/es/components/Tag/SelectableTag.js +2 -0
  106. package/es/components/Tag/Tag.js +4 -0
  107. package/es/components/Tag/isEllipsisActive.js +1 -0
  108. package/es/components/Text/Text.js +1 -0
  109. package/es/components/TextArea/TextArea.js +13 -6
  110. package/es/components/TextInput/ControlledPasswordInput.js +4 -6
  111. package/es/components/TextInput/PasswordInput.js +9 -4
  112. package/es/components/TextInput/TextInput.js +6 -4
  113. package/es/components/TextInput/util.d.ts +17 -5
  114. package/es/components/TextInput/util.js +2 -7
  115. package/es/components/Theme/index.js +8 -3
  116. package/es/components/Tile/Tile.js +14 -17
  117. package/es/components/TimePicker/TimePicker.js +1 -0
  118. package/es/components/Toggle/Toggle.js +1 -1
  119. package/es/components/Toggletip/index.js +4 -0
  120. package/es/components/Tooltip/DefinitionTooltip.js +1 -0
  121. package/es/components/Tooltip/Tooltip.js +30 -23
  122. package/es/components/TreeView/TreeNode.js +13 -5
  123. package/es/components/TreeView/TreeView.js +7 -0
  124. package/es/components/UIShell/HeaderContainer.js +3 -1
  125. package/es/components/UIShell/HeaderGlobalAction.js +2 -2
  126. package/es/components/UIShell/HeaderMenu.js +3 -3
  127. package/es/components/UIShell/HeaderPanel.d.ts +1 -1
  128. package/es/components/UIShell/HeaderPanel.js +2 -2
  129. package/es/components/UIShell/Link.js +2 -0
  130. package/es/components/UIShell/SideNavItems.js +1 -0
  131. package/es/components/UIShell/SideNavMenu.js +2 -2
  132. package/es/components/UIShell/SideNavMenuItem.js +1 -1
  133. package/es/components/UIShell/SideNavSwitcher.js +1 -1
  134. package/es/components/UIShell/Switcher.js +2 -1
  135. package/es/components/UIShell/SwitcherItem.js +4 -2
  136. package/es/index.d.ts +12 -13
  137. package/es/index.js +25 -24
  138. package/es/internal/FloatingMenu.js +7 -1
  139. package/es/internal/Selection.js +12 -3
  140. package/es/internal/defaultItemToString.d.ts +7 -0
  141. package/es/internal/defaultItemToString.js +17 -0
  142. package/es/internal/index.d.ts +1 -0
  143. package/es/internal/useMergedRefs.js +1 -0
  144. package/es/internal/useNoInteractiveChildren.js +4 -0
  145. package/es/internal/useOutsideClick.js +1 -0
  146. package/es/internal/useOverflowItems.js +6 -0
  147. package/es/internal/useResizeObserver.js +4 -0
  148. package/es/internal/useSavedCallback.js +1 -0
  149. package/es/internal/warning.js +1 -0
  150. package/es/prop-types/deprecateValuesWithin.d.ts +8 -1
  151. package/es/prop-types/deprecateValuesWithin.js +6 -6
  152. package/es/prop-types/isRequiredOneOf.js +4 -1
  153. package/es/prop-types/requiredIfGivenPropIsTruthy.d.ts +8 -7
  154. package/es/prop-types/requiredIfGivenPropIsTruthy.js +10 -10
  155. package/es/tools/events.js +3 -1
  156. package/es/tools/wrapComponent.js +1 -0
  157. package/lib/components/AILabel/index.js +8 -6
  158. package/lib/components/Breadcrumb/BreadcrumbItem.js +2 -0
  159. package/lib/components/Button/Button.js +3 -0
  160. package/lib/components/ChatButton/ChatButton.js +1 -0
  161. package/lib/components/CheckboxGroup/CheckboxGroup.js +20 -1
  162. package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  163. package/lib/components/CodeSnippet/CodeSnippet.js +1 -1
  164. package/lib/components/ComboBox/ComboBox.js +20 -15
  165. package/lib/components/ComboButton/index.js +2 -1
  166. package/lib/components/ComposedModal/ComposedModal.js +5 -2
  167. package/lib/components/Copy/Copy.d.ts +1 -1
  168. package/lib/components/Copy/Copy.js +1 -1
  169. package/lib/components/CopyButton/CopyButton.d.ts +1 -1
  170. package/lib/components/CopyButton/CopyButton.js +1 -1
  171. package/lib/components/DataTable/DataTable.d.ts +60 -15
  172. package/lib/components/DataTable/DataTable.js +119 -178
  173. package/lib/components/DataTable/Table.d.ts +2 -2
  174. package/lib/components/DataTable/Table.js +4 -4
  175. package/lib/components/DataTable/TableExpandHeader.d.ts +1 -1
  176. package/lib/components/DataTable/TableExpandHeader.js +6 -2
  177. package/lib/components/DataTable/TableExpandRow.js +1 -0
  178. package/lib/components/DataTable/TableHeader.js +2 -0
  179. package/lib/components/DataTable/TableRow.js +5 -0
  180. package/lib/components/DataTable/TableSlugRow.js +1 -0
  181. package/lib/components/DataTable/TableToolbarMenu.js +3 -0
  182. package/lib/components/DataTable/state/sorting.d.ts +3 -1
  183. package/lib/components/DataTable/state/sorting.js +2 -0
  184. package/lib/components/DataTable/tools/sorting.js +1 -0
  185. package/lib/components/DatePicker/DatePicker.d.ts +0 -12
  186. package/lib/components/DatePicker/DatePicker.js +16 -5
  187. package/lib/components/DatePicker/plugins/rangePlugin.d.ts +19 -2
  188. package/lib/components/DatePicker/plugins/rangePlugin.js +18 -16
  189. package/lib/components/DatePickerInput/DatePickerInput.js +6 -0
  190. package/lib/components/Dialog/Dialog.js +10 -2
  191. package/lib/components/Dropdown/Dropdown.js +19 -18
  192. package/lib/components/ErrorBoundary/ErrorBoundaryContext.js +1 -0
  193. package/lib/components/FeatureFlags/index.js +1 -0
  194. package/lib/components/FileUploader/FileUploader.js +9 -2
  195. package/lib/components/FileUploader/FileUploaderButton.js +1 -1
  196. package/lib/components/FileUploader/FileUploaderDropContainer.js +1 -1
  197. package/lib/components/FileUploader/FileUploaderItem.js +3 -0
  198. package/lib/components/FluidMultiSelect/FluidMultiSelect.js +2 -0
  199. package/lib/components/FluidNumberInput/FluidNumberInput.js +3 -2
  200. package/lib/components/FluidSearch/FluidSearch.js +3 -2
  201. package/lib/components/FluidSelect/FluidSelect.js +3 -2
  202. package/lib/components/FluidTextInput/FluidTextInput.js +3 -2
  203. package/lib/components/FluidTimePicker/FluidTimePicker.js +11 -4
  204. package/lib/components/FluidTimePickerSelect/FluidTimePickerSelect.js +3 -2
  205. package/lib/components/Grid/CSSGrid.js +5 -0
  206. package/lib/components/Grid/Column.js +3 -0
  207. package/lib/components/Grid/ColumnHang.js +1 -0
  208. package/lib/components/Grid/FlexGrid.js +1 -0
  209. package/lib/components/Grid/Row.js +1 -0
  210. package/lib/components/Heading/index.js +3 -1
  211. package/lib/components/IconButton/index.js +5 -3
  212. package/lib/components/IconIndicator/index.js +4 -2
  213. package/lib/components/InlineCheckbox/InlineCheckbox.js +3 -2
  214. package/lib/components/Layout/index.js +6 -4
  215. package/lib/components/LayoutDirection/LayoutDirection.js +2 -0
  216. package/lib/components/Link/Link.js +3 -0
  217. package/lib/components/ListBox/ListBoxMenuItem.js +4 -1
  218. package/lib/components/ListBox/next/ListBoxTrigger.js +3 -2
  219. package/lib/components/Menu/Menu.js +6 -9
  220. package/lib/components/Menu/MenuContext.js +1 -0
  221. package/lib/components/Menu/MenuItem.d.ts +1 -1
  222. package/lib/components/Menu/MenuItem.js +11 -19
  223. package/lib/components/MenuButton/index.js +7 -2
  224. package/lib/components/Modal/Modal.js +4 -1
  225. package/lib/components/ModalWrapper/ModalWrapper.js +2 -0
  226. package/lib/components/MultiSelect/FilterableMultiSelect.js +32 -13
  227. package/lib/components/MultiSelect/MultiSelect.js +23 -18
  228. package/lib/components/Notification/Notification.d.ts +6 -6
  229. package/lib/components/Notification/Notification.js +7 -7
  230. package/lib/components/NumberInput/NumberInput.js +7 -1
  231. package/lib/components/OverflowMenu/OverflowMenu.js +3 -1
  232. package/lib/components/OverflowMenu/next/index.js +4 -3
  233. package/lib/components/OverflowMenuItem/OverflowMenuItem.js +2 -0
  234. package/lib/components/PageHeader/PageHeader.d.ts +3 -3
  235. package/lib/components/PageHeader/PageHeader.js +22 -8
  236. package/lib/components/Pagination/Pagination.js +6 -2
  237. package/lib/components/PaginationNav/PaginationNav.js +2 -5
  238. package/lib/components/Popover/index.js +15 -5
  239. package/lib/components/ProgressBar/ProgressBar.js +4 -2
  240. package/lib/components/RadioTile/RadioTile.js +2 -2
  241. package/lib/components/Search/Search.d.ts +4 -2
  242. package/lib/components/Search/Search.js +7 -6
  243. package/lib/components/Select/Select.js +2 -3
  244. package/lib/components/ShapeIndicator/index.js +4 -2
  245. package/lib/components/SkeletonPlaceholder/SkeletonPlaceholder.d.ts +4 -4
  246. package/lib/components/SkeletonPlaceholder/SkeletonPlaceholder.js +1 -2
  247. package/lib/components/SkeletonText/SkeletonText.js +0 -2
  248. package/lib/components/Slider/Slider.d.ts +144 -188
  249. package/lib/components/Slider/Slider.js +795 -725
  250. package/lib/components/Slider/index.d.ts +2 -2
  251. package/lib/components/Stack/HStack.js +1 -0
  252. package/lib/components/Stack/Stack.js +6 -9
  253. package/lib/components/Stack/VStack.js +1 -0
  254. package/lib/components/StructuredList/StructuredList.js +3 -0
  255. package/lib/components/Switch/Switch.js +1 -1
  256. package/lib/components/Tabs/Tabs.d.ts +4 -0
  257. package/lib/components/Tabs/Tabs.js +28 -17
  258. package/lib/components/Tag/DismissibleTag.js +2 -0
  259. package/lib/components/Tag/OperationalTag.js +2 -0
  260. package/lib/components/Tag/SelectableTag.js +2 -0
  261. package/lib/components/Tag/Tag.js +4 -0
  262. package/lib/components/Tag/isEllipsisActive.js +1 -0
  263. package/lib/components/Text/Text.js +1 -0
  264. package/lib/components/TextArea/TextArea.js +13 -6
  265. package/lib/components/TextInput/ControlledPasswordInput.js +3 -5
  266. package/lib/components/TextInput/PasswordInput.js +8 -3
  267. package/lib/components/TextInput/TextInput.js +5 -3
  268. package/lib/components/TextInput/util.d.ts +17 -5
  269. package/lib/components/TextInput/util.js +2 -7
  270. package/lib/components/Theme/index.js +8 -3
  271. package/lib/components/Tile/Tile.js +14 -17
  272. package/lib/components/TimePicker/TimePicker.js +1 -0
  273. package/lib/components/Toggle/Toggle.js +1 -1
  274. package/lib/components/Toggletip/index.js +4 -0
  275. package/lib/components/Tooltip/DefinitionTooltip.js +1 -0
  276. package/lib/components/Tooltip/Tooltip.js +30 -23
  277. package/lib/components/TreeView/TreeNode.js +13 -5
  278. package/lib/components/TreeView/TreeView.js +7 -0
  279. package/lib/components/UIShell/HeaderContainer.js +3 -1
  280. package/lib/components/UIShell/HeaderGlobalAction.js +2 -2
  281. package/lib/components/UIShell/HeaderMenu.js +3 -3
  282. package/lib/components/UIShell/HeaderPanel.d.ts +1 -1
  283. package/lib/components/UIShell/HeaderPanel.js +2 -2
  284. package/lib/components/UIShell/Link.js +2 -0
  285. package/lib/components/UIShell/SideNavItems.js +1 -0
  286. package/lib/components/UIShell/SideNavMenu.js +2 -2
  287. package/lib/components/UIShell/SideNavMenuItem.js +1 -1
  288. package/lib/components/UIShell/SideNavSwitcher.js +1 -1
  289. package/lib/components/UIShell/Switcher.js +2 -1
  290. package/lib/components/UIShell/SwitcherItem.js +4 -2
  291. package/lib/index.d.ts +12 -13
  292. package/lib/index.js +51 -28
  293. package/lib/internal/FloatingMenu.js +7 -1
  294. package/lib/internal/Selection.js +12 -3
  295. package/lib/internal/defaultItemToString.d.ts +7 -0
  296. package/lib/internal/defaultItemToString.js +19 -0
  297. package/lib/internal/index.d.ts +1 -0
  298. package/lib/internal/useMergedRefs.js +1 -0
  299. package/lib/internal/useNoInteractiveChildren.js +4 -0
  300. package/lib/internal/useOutsideClick.js +1 -0
  301. package/lib/internal/useOverflowItems.js +6 -0
  302. package/lib/internal/useResizeObserver.js +4 -0
  303. package/lib/internal/useSavedCallback.js +1 -0
  304. package/lib/internal/warning.js +1 -0
  305. package/lib/prop-types/deprecateValuesWithin.d.ts +8 -1
  306. package/lib/prop-types/deprecateValuesWithin.js +6 -8
  307. package/lib/prop-types/isRequiredOneOf.js +4 -1
  308. package/lib/prop-types/requiredIfGivenPropIsTruthy.d.ts +8 -7
  309. package/lib/prop-types/requiredIfGivenPropIsTruthy.js +10 -12
  310. package/lib/tools/events.js +3 -1
  311. package/lib/tools/wrapComponent.js +1 -0
  312. package/package.json +10 -9
  313. package/es/components/MultiSelect/tools/itemToString.d.ts +0 -1
  314. package/es/components/MultiSelect/tools/itemToString.js +0 -21
  315. package/es/components/Slider/index.js +0 -14
  316. package/es/internal/createClassWrapper.js +0 -23
  317. package/lib/components/MultiSelect/tools/itemToString.d.ts +0 -1
  318. package/lib/components/MultiSelect/tools/itemToString.js +0 -23
  319. package/lib/components/Slider/index.js +0 -20
  320. package/lib/internal/createClassWrapper.js +0 -25
@@ -7,8 +7,6 @@
7
7
 
8
8
  'use strict';
9
9
 
10
- Object.defineProperty(exports, '__esModule', { value: true });
11
-
12
10
  var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
13
11
  var React = require('react');
14
12
  var PropTypes = require('prop-types');
@@ -17,7 +15,6 @@ var keys = require('../../internal/keyboard/keys.js');
17
15
  var match = require('../../internal/keyboard/match.js');
18
16
  var usePrefix = require('../../internal/usePrefix.js');
19
17
  var deprecate = require('../../prop-types/deprecate.js');
20
- var index = require('../FeatureFlags/index.js');
21
18
  var iconsReact = require('@carbon/icons-react');
22
19
  require('../Text/index.js');
23
20
  require('../Tooltip/DefinitionTooltip.js');
@@ -35,23 +32,15 @@ const ThumbWrapper = ({
35
32
  ...rest
36
33
  }) => {
37
34
  if (hasTooltip) {
38
- return (
39
- /*#__PURE__*/
40
- // eslint-disable-next-line react/forbid-component-props
41
- React.createElement(Tooltip.Tooltip, _rollupPluginBabelHelpers.extends({
42
- className: className,
43
- style: style
44
- }, rest), children)
45
- );
35
+ return /*#__PURE__*/React.createElement(Tooltip.Tooltip, _rollupPluginBabelHelpers.extends({
36
+ className: className,
37
+ style: style
38
+ }, rest), children);
46
39
  } else {
47
- return (
48
- /*#__PURE__*/
49
- // eslint-disable-next-line react/forbid-dom-props
50
- React.createElement("div", {
51
- className: className,
52
- style: style
53
- }, children)
54
- );
40
+ return /*#__PURE__*/React.createElement("div", {
41
+ className: className,
42
+ style: style
43
+ }, children);
55
44
  }
56
45
  };
57
46
  const translationIds = {
@@ -88,752 +77,834 @@ var HandlePosition = /*#__PURE__*/function (HandlePosition) {
88
77
  HandlePosition["LOWER"] = "lower";
89
78
  HandlePosition["UPPER"] = "upper";
90
79
  return HandlePosition;
91
- }(HandlePosition || {});
92
- class Slider extends React.PureComponent {
93
- constructor(props) {
94
- super(props);
95
- _rollupPluginBabelHelpers.defineProperty(this, "state", {
96
- value: this.props.value,
97
- valueUpper: this.props.unstable_valueUpper,
98
- left: 0,
99
- leftUpper: 0,
100
- needsOnRelease: false,
101
- isValid: true,
102
- isValidUpper: true,
103
- activeHandle: undefined,
104
- correctedValue: null,
105
- correctedPosition: null,
106
- isRtl: false
107
- });
108
- _rollupPluginBabelHelpers.defineProperty(this, "thumbRef", void 0);
109
- _rollupPluginBabelHelpers.defineProperty(this, "thumbRefUpper", void 0);
110
- _rollupPluginBabelHelpers.defineProperty(this, "filledTrackRef", void 0);
111
- _rollupPluginBabelHelpers.defineProperty(this, "element", null);
112
- _rollupPluginBabelHelpers.defineProperty(this, "inputId", '');
113
- _rollupPluginBabelHelpers.defineProperty(this, "track", void 0);
114
- _rollupPluginBabelHelpers.defineProperty(this, "handleDrag", event => {
115
- if (event instanceof globalThis.MouseEvent || event instanceof globalThis.TouchEvent) {
116
- this.onDrag(event);
117
- }
118
- });
119
- /**
120
- * Sets up "drag" event handlers and calls `this.onDrag` in case dragging
121
- * started on somewhere other than the thumb without a corresponding "move"
122
- * event.
123
- */
124
- _rollupPluginBabelHelpers.defineProperty(this, "onDragStart", evt => {
125
- // Do nothing if component is disabled
126
- if (this.props.disabled || this.props.readOnly) {
127
- return;
128
- }
129
-
130
- // We're going to force focus on one of the handles later on here, b/c we're
131
- // firing on a mousedown event, we need to call event.preventDefault() to
132
- // keep the focus from leaving the HTMLElement.
133
- // @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#notes
134
- evt.preventDefault();
135
-
136
- // Add drag stop handlers
137
- DRAG_STOP_EVENT_TYPES.forEach(element => {
138
- this.element?.ownerDocument.addEventListener(element, this.onDragStop);
139
- });
140
-
141
- // Add drag handlers
142
- DRAG_EVENT_TYPES.forEach(element => {
143
- this.element?.ownerDocument.addEventListener(element, this.handleDrag);
144
- });
145
- const clientX = this.getClientXFromEvent(evt.nativeEvent);
146
- let activeHandle;
147
- if (this.hasTwoHandles()) {
148
- if (evt.target == this.thumbRef.current) {
149
- activeHandle = HandlePosition.LOWER;
150
- } else if (evt.target == this.thumbRefUpper.current) {
151
- activeHandle = HandlePosition.UPPER;
152
- } else if (clientX) {
153
- const distanceToLower = this.calcDistanceToHandle(HandlePosition.LOWER, clientX);
154
- const distanceToUpper = this.calcDistanceToHandle(HandlePosition.UPPER, clientX);
155
- if (distanceToLower <= distanceToUpper) {
156
- activeHandle = HandlePosition.LOWER;
157
- } else {
158
- activeHandle = HandlePosition.UPPER;
159
- }
160
- }
161
- }
80
+ }(HandlePosition || {}); // TODO: Delete this type and directory type the properties in the function.
81
+ const Slider = props => {
82
+ // TODO: Move destructured `props` from the IIFE to here.
162
83
 
163
- // Force focus to the appropriate handle.
164
- const focusOptions = {
165
- preventScroll: true
166
- };
167
- if (this.hasTwoHandles()) {
168
- if (this.thumbRef.current && activeHandle === HandlePosition.LOWER) {
169
- this.thumbRef.current.focus(focusOptions);
170
- } else if (this.thumbRefUpper.current && activeHandle === HandlePosition.UPPER) {
171
- this.thumbRefUpper.current.focus(focusOptions);
172
- }
173
- } else if (this.thumbRef.current) {
174
- this.thumbRef.current.focus(focusOptions);
175
- }
176
- this.setState({
177
- activeHandle
178
- });
84
+ const initialState = {
85
+ value: props.value,
86
+ valueUpper: props.unstable_valueUpper,
87
+ left: 0,
88
+ leftUpper: 0,
89
+ needsOnRelease: false,
90
+ isValid: true,
91
+ isValidUpper: true,
92
+ activeHandle: undefined,
93
+ correctedValue: null,
94
+ correctedPosition: null,
95
+ isRtl: false
96
+ };
179
97
 
180
- // Perform first recalculation since we probably didn't click exactly in the
181
- // middle of the thumb.
182
- this.onDrag(evt.nativeEvent, activeHandle);
183
- });
184
- /**
185
- * Removes "drag" and "drag stop" event handlers and calls sets the flag
186
- * indicating that the `onRelease` callback should be called.
187
- */
188
- _rollupPluginBabelHelpers.defineProperty(this, "onDragStop", () => {
189
- // Do nothing if component is disabled
190
- if (this.props.disabled || this.props.readOnly) {
191
- return;
192
- }
98
+ // TODO: Investigate using generics on the hook.
99
+ const [state, setState] = React.useReducer((prev, args) => ({
100
+ ...prev,
101
+ ...args
102
+ }), initialState);
193
103
 
194
- // Remove drag stop handlers
195
- DRAG_STOP_EVENT_TYPES.forEach(element => {
196
- this.element?.ownerDocument.removeEventListener(element, this.onDragStop);
197
- });
104
+ // TODO: Investigate getting rid of these references.
105
+ const stateRef = React.useRef(state);
106
+ React.useEffect(() => {
107
+ stateRef.current = state;
108
+ }, [state]);
109
+ const propsRef = React.useRef(props);
110
+ React.useEffect(() => {
111
+ propsRef.current = props;
112
+ }, [props]);
113
+ const thumbRef = React.useRef(null);
114
+ const thumbRefUpper = React.useRef(null);
115
+ const filledTrackRef = React.useRef(null);
116
+ const elementRef = React.useRef(null);
117
+ const trackRef = React.useRef(null);
118
+ const inputIdRef = React.useRef('');
198
119
 
199
- // Remove drag handlers
200
- DRAG_EVENT_TYPES.forEach(element => {
201
- this.element?.ownerDocument.removeEventListener(element, this.handleDrag);
202
- });
120
+ // TODO: Delete this function and set its return value as the value of
121
+ // `twoHandles`.
122
+ const hasTwoHandles = () => {
123
+ return typeof state.valueUpper !== 'undefined';
124
+ };
125
+ const twoHandles = hasTwoHandles();
203
126
 
204
- // Set needsOnRelease flag so event fires on next update.
205
- this.setState({
206
- needsOnRelease: true,
207
- isValid: true,
208
- isValidUpper: true
209
- });
210
- });
211
- /**
212
- * Handles a "drag" event by recalculating the value/thumb and setting state
213
- * accordingly.
214
- *
215
- * @param evt The event.
216
- * @param activeHandle The first drag event call, we may have an explicit
217
- * activeHandle value, which is to be used before state is used.
218
- */
219
- _rollupPluginBabelHelpers.defineProperty(this, "_onDrag", (evt, activeHandle) => {
220
- activeHandle = activeHandle ?? this.state.activeHandle;
221
- // Do nothing if component is disabled, or we have no event.
222
- if (this.props.disabled || this.props.readOnly || !evt) {
223
- return;
224
- }
225
- const clientX = this.getClientXFromEvent(evt);
226
- const {
227
- value,
228
- left
229
- } = this.calcValue({
230
- clientX,
231
- value: this.state.value
232
- });
233
- // If we're set to two handles, negotiate which drag handle is closest to
234
- // the users' interaction.
235
- if (this.hasTwoHandles() && activeHandle) {
236
- this.setValueLeftForHandle(activeHandle, {
237
- value: this.nearestStepValue(value),
127
+ /**
128
+ * Sets up initial slider position and value in response to component mount.
129
+ */
130
+ React.useEffect(() => {
131
+ if (elementRef.current) {
132
+ const isRtl = document?.dir === 'rtl';
133
+ if (hasTwoHandles()) {
134
+ const {
135
+ value,
238
136
  left
137
+ } = calcValue({
138
+ value: stateRef.current.value,
139
+ useRawValue: true
239
140
  });
240
- } else {
241
- this.setState({
242
- value: this.nearestStepValue(value),
141
+ const {
142
+ value: valueUpper,
143
+ left: leftUpper
144
+ } = calcValue({
145
+ value: stateRef.current.valueUpper,
146
+ useRawValue: true
147
+ });
148
+ setState({
149
+ isRtl,
150
+ value,
243
151
  left,
244
- isValid: true
152
+ valueUpper,
153
+ leftUpper
245
154
  });
246
- }
247
- this.setState({
248
- correctedValue: null,
249
- correctedPosition: null
250
- });
251
- });
252
- /**
253
- * Throttles calls to `this._onDrag` by limiting events to being processed at
254
- * most once every `EVENT_THROTTLE` milliseconds.
255
- */
256
- _rollupPluginBabelHelpers.defineProperty(this, "onDrag", throttle.throttle(this._onDrag, EVENT_THROTTLE, {
257
- leading: true,
258
- trailing: false
259
- }));
260
- /**
261
- * Handles a `keydown` event by recalculating the value/thumb and setting
262
- * state accordingly.
263
- */
264
- _rollupPluginBabelHelpers.defineProperty(this, "onKeyDown", evt => {
265
- // Do nothing if component is disabled, or we don't have a valid event
266
- if (this.props.disabled || this.props.readOnly) {
267
- return;
268
- }
269
- const {
270
- step = 1,
271
- stepMultiplier = 4
272
- } = this.props;
273
- let delta = 0;
274
- if (match.matches(evt, [keys.ArrowDown, keys.ArrowLeft])) {
275
- delta = -step;
276
- } else if (match.matches(evt, [keys.ArrowUp, keys.ArrowRight])) {
277
- delta = step;
278
155
  } else {
279
- // Ignore keys we don't want to handle
280
- return;
281
- }
282
-
283
- // If shift was held, account for the stepMultiplier
284
- if (evt.shiftKey) {
285
- delta *= stepMultiplier;
286
- }
287
- if (this.hasTwoHandles() && this.state.activeHandle) {
288
- const currentValue = this.state.activeHandle === HandlePosition.LOWER ? this.state.value : this.state.valueUpper;
289
156
  const {
290
157
  value,
291
158
  left
292
- } = this.calcValue({
293
- value: this.calcValueForDelta(currentValue ?? this.props.min, delta, this.props.step)
294
- });
295
- this.setValueLeftForHandle(this.state.activeHandle, {
296
- value: this.nearestStepValue(value),
297
- left
159
+ } = calcValue({
160
+ value: stateRef.current.value,
161
+ useRawValue: true
298
162
  });
299
- } else {
300
- const {
163
+ setState({
164
+ isRtl,
301
165
  value,
302
166
  left
303
- } = this.calcValue({
304
- // Ensures custom value from `<input>` won't cause skipping next stepping
305
- // point with right arrow key, e.g. Typing 51 in `<input>`, moving focus
306
- // onto the thumb and the hitting right arrow key should yield 52 instead
307
- // of 54.
308
- value: this.calcValueForDelta(this.state.value, delta, this.props.step)
309
- });
310
- this.setState({
311
- value: this.nearestStepValue(value),
312
- left,
313
- isValid: true
314
167
  });
315
168
  }
316
- this.setState({
317
- correctedValue: null,
318
- correctedPosition: null
319
- });
320
- });
321
- /**
322
- * Provides the two-way binding for the input field of the Slider. It also
323
- * Handles a change to the input field by recalculating the value/thumb and
324
- * setting state accordingly.
325
- */
326
- _rollupPluginBabelHelpers.defineProperty(this, "onChange", evt => {
327
- // Do nothing if component is disabled
328
- if (this.props.disabled || this.props.readOnly) {
329
- return;
330
- }
331
-
332
- // Do nothing if we have no valid event, target, or value
333
- if (!evt || !('target' in evt) || typeof evt.target.value !== 'string') {
334
- return;
335
- }
169
+ }
170
+ return () => {
171
+ DRAG_STOP_EVENT_TYPES.forEach(element => elementRef.current?.ownerDocument.removeEventListener(element, onDragStop));
172
+ DRAG_EVENT_TYPES.forEach(element => elementRef.current?.ownerDocument.removeEventListener(element, handleDrag));
173
+ };
174
+ // eslint-disable-next-line react-hooks/exhaustive-deps
175
+ }, []);
176
+ React.useEffect(() => {
177
+ // TODO: Uncomment this code and delete all of the `filledTrackRef.current`
178
+ // checks.
179
+ // const el = filledTrackRef.current;
180
+ //
181
+ // if (!el) return;
336
182
 
337
- // Avoid calling calcValue for invalid numbers, but still update the state.
338
- const activeHandle = evt.target.dataset.handlePosition ?? HandlePosition.LOWER;
339
- const targetValue = Number.parseFloat(evt.target.value);
340
- if (this.hasTwoHandles()) {
341
- if (isNaN(targetValue)) {
342
- this.setValueForHandle(activeHandle, evt.target.value);
343
- } else if (this.isValidValueForPosition({
344
- handle: activeHandle,
345
- value: targetValue,
346
- min: this.props.min,
347
- max: this.props.max
348
- })) {
349
- this.processNewInputValue(evt.target);
350
- } else {
351
- this.setValueForHandle(activeHandle, targetValue);
352
- }
353
- } else {
354
- if (isNaN(targetValue)) {
355
- this.setState({
356
- value: evt.target.value
357
- });
358
- } else if (this.isValidValue({
359
- value: targetValue,
360
- min: this.props.min,
361
- max: this.props.max
362
- })) {
363
- this.processNewInputValue(evt.target);
364
- } else {
365
- this.setState({
366
- value: targetValue
367
- });
368
- }
369
- }
370
- });
371
- /**
372
- * Checks for validity of input value after clicking out of the input. It also
373
- * Handles state change to isValid state.
374
- */
375
- _rollupPluginBabelHelpers.defineProperty(this, "onBlur", evt => {
376
- // Do nothing if we have no valid event, target, or value
377
- if (!evt || !('target' in evt) || typeof evt.target.value !== 'string') {
378
- return;
183
+ // Fire onChange event handler if present, if there's a usable value, and
184
+ // if the value is different from the last one
185
+ if (hasTwoHandles()) {
186
+ if (filledTrackRef.current) {
187
+ filledTrackRef.current.style.transform = state.isRtl ? `translate(${100 - state.leftUpper}%, -50%) scaleX(${(state.leftUpper - state.left) / 100})` : `translate(${state.left}%, -50%) scaleX(${(state.leftUpper - state.left) / 100})`;
379
188
  }
380
- const {
381
- value: targetValue
382
- } = evt.target;
383
- this.processNewInputValue(evt.target);
384
- this.props.onBlur?.({
385
- value: targetValue,
386
- handlePosition: evt.target.dataset.handlePosition
387
- });
388
- });
389
- _rollupPluginBabelHelpers.defineProperty(this, "onInputKeyDown", evt => {
390
- // Do nothing if component is disabled, or we don't have a valid event.
391
- if (this.props.disabled || this.props.readOnly || !(evt.target instanceof HTMLInputElement)) {
392
- return;
189
+ } else {
190
+ if (filledTrackRef.current) {
191
+ filledTrackRef.current.style.transform = state.isRtl ? `translate(100%, -50%) scaleX(-${state.left / 100})` : `translate(0%, -50%) scaleX(${state.left / 100})`;
393
192
  }
193
+ }
194
+ // TODO: Investigate whether the missing dependency should be added.
195
+ //
196
+ // eslint-disable-next-line react-hooks/exhaustive-deps
197
+ }, [state.left, state.leftUpper, state.isRtl]);
394
198
 
395
- // Do nothing if we have no valid event, target, or value.
396
- if (!evt || !('target' in evt) || typeof evt.target.value !== 'string') {
397
- return;
398
- }
399
- if (match.matches(evt, [keys.Enter])) {
400
- this.processNewInputValue(evt.target);
401
- }
402
- });
403
- _rollupPluginBabelHelpers.defineProperty(this, "processNewInputValue", input => {
404
- this.setState({
405
- correctedValue: null,
406
- correctedPosition: null
199
+ // Fire onChange when value(s) change
200
+ const prevValsRef = React.useRef(null);
201
+ React.useEffect(() => {
202
+ const prev = prevValsRef.current;
203
+ if (prev && (prev.value !== state.value || prev.valueUpper !== state.valueUpper) && typeof props.onChange === 'function') {
204
+ props.onChange({
205
+ value: state.value,
206
+ valueUpper: state.valueUpper
407
207
  });
408
- const targetValue = Number.parseFloat(input.value);
409
- const validity = !isNaN(targetValue);
410
-
411
- // When there are two handles, we'll also have the data-handle-position
412
- // attribute to consider the other value before settling on the validity to
413
- // set.
414
- const handlePosition = input.dataset.handlePosition;
415
- if (handlePosition === HandlePosition.LOWER) {
416
- this.setState({
417
- isValid: validity
418
- });
419
- } else if (handlePosition === HandlePosition.UPPER) {
420
- this.setState({
421
- isValidUpper: validity
422
- });
423
- }
424
- this.setState({
425
- isValid: validity
208
+ }
209
+ prevValsRef.current = {
210
+ value: state.value,
211
+ valueUpper: state.valueUpper
212
+ };
213
+ // TODO: Investigate whether the missing dependency should be added.
214
+ //
215
+ // eslint-disable-next-line react-hooks/exhaustive-deps
216
+ }, [state.value, state.valueUpper, props.onChange]);
217
+ React.useEffect(() => {
218
+ // Fire onRelease event handler if present and if needed
219
+ if (state.needsOnRelease && typeof props.onRelease === 'function') {
220
+ props.onRelease({
221
+ value: state.value,
222
+ valueUpper: state.valueUpper
426
223
  });
427
- if (validity) {
428
- const adjustedValue = handlePosition ? this.getAdjustedValueForPosition({
429
- handle: handlePosition,
430
- value: targetValue,
431
- min: this.props.min,
432
- max: this.props.max
433
- }) : this.getAdjustedValue({
434
- value: targetValue,
435
- min: this.props.min,
436
- max: this.props.max
437
- });
438
- if (adjustedValue !== targetValue) {
439
- this.setState({
440
- correctedValue: targetValue.toString(),
441
- correctedPosition: handlePosition
442
- });
443
- } else {
444
- this.setState({
445
- correctedValue: null,
446
- correctedPosition: null
447
- });
448
- }
224
+ // Reset the flag
225
+ setState({
226
+ needsOnRelease: false
227
+ });
228
+ }
229
+ // TODO: Investigate whether the missing dependency should be added.
230
+ //
231
+ // eslint-disable-next-line react-hooks/exhaustive-deps
232
+ }, [state.needsOnRelease, state.value, state.valueUpper, props.onRelease]);
233
+ const prevSyncKeysRef = React.useRef(null);
234
+ React.useEffect(() => {
235
+ const prev = prevSyncKeysRef.current;
236
+ const next = [props.value, props.unstable_valueUpper, props.max, props.min];
237
+
238
+ // If value from props does not change, do nothing here.
239
+ // Otherwise, do prop -> state sync without "value capping".
240
+ if (!prev || prev[0] !== next[0] || prev[1] !== next[1] || prev[2] !== next[2] || prev[3] !== next[3]) {
241
+ setState(calcValue({
242
+ value: props.value,
243
+ useRawValue: true
244
+ }));
245
+ if (typeof props.unstable_valueUpper !== 'undefined') {
449
246
  const {
450
- value,
451
- left
452
- } = this.calcValue({
453
- value: adjustedValue,
247
+ value: valueUpper,
248
+ left: leftUpper
249
+ } = calcValue({
250
+ value: props.unstable_valueUpper,
454
251
  useRawValue: true
455
252
  });
456
- if (handlePosition) {
457
- this.setValueLeftForHandle(handlePosition, {
458
- value: this.nearestStepValue(value),
459
- left
460
- });
461
- } else {
462
- this.setState({
463
- value,
464
- left
465
- });
466
- }
253
+ setState({
254
+ valueUpper,
255
+ leftUpper
256
+ });
257
+ } else {
258
+ setState({
259
+ valueUpper: undefined,
260
+ leftUpper: undefined
261
+ });
467
262
  }
263
+ prevSyncKeysRef.current = next;
264
+ }
265
+ // TODO: Investigate whether the missing dependency should be added.
266
+ //
267
+ // eslint-disable-next-line react-hooks/exhaustive-deps
268
+ }, [props.value, props.unstable_valueUpper, props.max, props.min]);
269
+
270
+ /**
271
+ * Rounds a given value to the nearest step defined by the slider's `step`
272
+ * prop.
273
+ *
274
+ * @param value - The value to adjust to the nearest step. Defaults to `0`.
275
+ * @returns The value rounded to the precision determined by the step.
276
+ */
277
+ const nearestStepValue = (value = 0) => {
278
+ // TODO: Use a nullish coalescing operator.
279
+ const decimals = (props.step?.toString().split('.')[1] || '').length;
280
+ return Number(value.toFixed(decimals));
281
+ };
282
+ const handleDrag = event => {
283
+ if (event instanceof globalThis.MouseEvent || event instanceof globalThis.TouchEvent) {
284
+ onDrag(event);
285
+ }
286
+ };
287
+
288
+ /**
289
+ * Sets up "drag" event handlers and calls `onDrag` in case dragging
290
+ * started on somewhere other than the thumb without a corresponding "move"
291
+ * event.
292
+ */
293
+ const onDragStart = evt => {
294
+ // Do nothing if component is disabled
295
+ if (props.disabled || props.readOnly) {
296
+ return;
297
+ }
298
+
299
+ // We're going to force focus on one of the handles later on here, b/c we're
300
+ // firing on a mousedown event, we need to call event.preventDefault() to
301
+ // keep the focus from leaving the HTMLElement.
302
+ // @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#notes
303
+ evt.preventDefault();
304
+
305
+ // TODO: Abstract `elementRef.current?.ownerDocument` to a variable that can
306
+ // be used here and everywhere else in this file.
307
+
308
+ // Add drag stop handlers
309
+ DRAG_STOP_EVENT_TYPES.forEach(element => {
310
+ elementRef.current?.ownerDocument.addEventListener(element, onDragStop);
468
311
  });
469
- _rollupPluginBabelHelpers.defineProperty(this, "calcLeftPercent", ({
470
- clientX,
471
- value,
472
- range
473
- }) => {
474
- const boundingRect = this.element?.getBoundingClientRect?.();
475
- let width = boundingRect ? boundingRect.right - boundingRect.left : 0;
476
312
 
477
- // Enforce a minimum width of at least 1 for calculations
478
- if (width <= 0) {
479
- width = 1;
313
+ // Add drag handlers
314
+ DRAG_EVENT_TYPES.forEach(element => {
315
+ elementRef.current?.ownerDocument.addEventListener(element, handleDrag);
316
+ });
317
+ const clientX = getClientXFromEvent(evt.nativeEvent);
318
+ let activeHandle;
319
+ if (hasTwoHandles()) {
320
+ if (evt.target == thumbRef.current) {
321
+ activeHandle = HandlePosition.LOWER;
322
+ } else if (evt.target == thumbRefUpper.current) {
323
+ activeHandle = HandlePosition.UPPER;
324
+ } else if (clientX) {
325
+ const distanceToLower = calcDistanceToHandle(HandlePosition.LOWER, clientX);
326
+ const distanceToUpper = calcDistanceToHandle(HandlePosition.UPPER, clientX);
327
+ if (distanceToLower <= distanceToUpper) {
328
+ activeHandle = HandlePosition.LOWER;
329
+ } else {
330
+ activeHandle = HandlePosition.UPPER;
331
+ }
480
332
  }
333
+ }
481
334
 
482
- // If a clientX is specified, use it to calculate the leftPercent. If not,
483
- // use the provided value to calculate it instead.
484
- if (clientX) {
485
- const leftOffset = this.state.isRtl ? (boundingRect?.right ?? 0) - clientX : clientX - (boundingRect?.left ?? 0);
486
- return leftOffset / width;
487
- } else if (value !== null && typeof value !== 'undefined' && range) {
488
- // Prevent NaN calculation if the range is 0.
489
- return range === 0 ? 0 : (value - this.props.min) / range;
335
+ // Force focus to the appropriate handle.
336
+ const focusOptions = {
337
+ preventScroll: true
338
+ };
339
+ if (hasTwoHandles()) {
340
+ if (thumbRef.current && activeHandle === HandlePosition.LOWER) {
341
+ thumbRef.current.focus(focusOptions);
342
+ } else if (thumbRefUpper.current && activeHandle === HandlePosition.UPPER) {
343
+ thumbRefUpper.current.focus(focusOptions);
490
344
  }
491
- // We should never end up in this scenario, but in case we do, and to
492
- // re-assure Typescript, return 0.
493
- return 0;
345
+ } else if (thumbRef.current) {
346
+ thumbRef.current.focus(focusOptions);
347
+ }
348
+ setState({
349
+ activeHandle
494
350
  });
495
- /**
496
- * Calculates the discrete value (snapped to the nearest step) along
497
- * with the corresponding handle position percentage.
498
- */
499
- _rollupPluginBabelHelpers.defineProperty(this, "calcDiscreteValueAndPercent", ({
500
- leftPercent
501
- }) => {
502
- const {
503
- step = 1,
504
- min,
505
- max
506
- } = this.props;
507
- const numSteps = Math.floor((max - min) / step) + ((max - min) % step === 0 ? 1 : 2);
508
- /** Index of the step that corresponds to `leftPercent`. */
509
- const stepIndex = Math.round(leftPercent * (numSteps - 1));
510
- const discreteValue = stepIndex === numSteps - 1 ? max : min + step * stepIndex;
511
- /** Percentage corresponding to the step index. */
512
- const discretePercent = stepIndex / (numSteps - 1);
513
- return {
514
- discreteValue,
515
- discretePercent
516
- };
351
+
352
+ // Perform first recalculation since we probably didn't click exactly in the
353
+ // middle of the thumb.
354
+ onDrag(evt.nativeEvent, activeHandle);
355
+ };
356
+
357
+ /**
358
+ * Removes "drag" and "drag stop" event handlers and calls sets the flag
359
+ * indicating that the `onRelease` callback should be called.
360
+ */
361
+ const onDragStop = () => {
362
+ // Do nothing if component is disabled
363
+ if (props.disabled || props.readOnly) {
364
+ return;
365
+ }
366
+
367
+ // TODO: Rename parameters in `DRAG_*` loops to `type`.
368
+ // Remove drag stop handlers
369
+ DRAG_STOP_EVENT_TYPES.forEach(element => {
370
+ elementRef.current?.ownerDocument.removeEventListener(element, onDragStop);
517
371
  });
518
- /**
519
- * Calculates the slider's value and handle position based on either a
520
- * mouse/touch event or an explicit value.
521
- */
522
- _rollupPluginBabelHelpers.defineProperty(this, "calcValue", ({
523
- clientX,
372
+
373
+ // Remove drag handlers
374
+ DRAG_EVENT_TYPES.forEach(element => {
375
+ elementRef.current?.ownerDocument.removeEventListener(element, handleDrag);
376
+ });
377
+
378
+ // Set needsOnRelease flag so event fires on next update.
379
+ setState({
380
+ needsOnRelease: true,
381
+ isValid: true,
382
+ isValidUpper: true
383
+ });
384
+ };
385
+
386
+ // TODO: Rename this reference.
387
+ /**
388
+ * Handles a "drag" event by recalculating the value/thumb and setting state
389
+ * accordingly.
390
+ *
391
+ * @param evt The event.
392
+ * @param activeHandle The first drag event call, we may have an explicit
393
+ * activeHandle value, which is to be used before state is used.
394
+ */
395
+ const _onDragRef = React.useRef(null);
396
+ _onDragRef.current = (evt, activeHandle) => {
397
+ activeHandle = activeHandle ?? stateRef.current.activeHandle;
398
+ // Do nothing if component is disabled, or we have no event.
399
+ if (propsRef.current.disabled || propsRef.current.readOnly || !evt) {
400
+ return;
401
+ }
402
+ const clientX = getClientXFromEvent(evt);
403
+ const {
524
404
  value,
525
- useRawValue
526
- }) => {
527
- const range = this.props.max - this.props.min;
528
- const leftPercentRaw = this.calcLeftPercent({
529
- clientX,
530
- value,
531
- range
405
+ left
406
+ } = calcValue({
407
+ clientX,
408
+ value: stateRef.current.value
409
+ });
410
+ // If we're set to two handles, negotiate which drag handle is closest to
411
+ // the users' interaction.
412
+ if (hasTwoHandles() && activeHandle) {
413
+ setValueLeftForHandle(activeHandle, {
414
+ value: nearestStepValue(value),
415
+ left
532
416
  });
533
- /** `leftPercentRaw` clamped between 0 and 1. */
534
- const leftPercent = clamp.clamp(leftPercentRaw, 0, 1);
535
- if (useRawValue) {
536
- return {
537
- value,
538
- left: leftPercent * 100
539
- };
540
- }
417
+ } else {
418
+ setState({
419
+ value: nearestStepValue(value),
420
+ left,
421
+ isValid: true
422
+ });
423
+ }
424
+ // TODO: Investigate if it would be better to not call `setState`
425
+ // back-to-back here and in other places.
426
+ setState({
427
+ correctedValue: null,
428
+ correctedPosition: null
429
+ });
430
+ };
431
+
432
+ /**
433
+ * Throttles calls to `_onDrag` by limiting events to being processed at
434
+ * most once every `EVENT_THROTTLE` milliseconds.
435
+ */
436
+ const onDrag = React.useMemo(() => throttle.throttle((evt, activeHandle) => {
437
+ _onDragRef.current?.(evt, activeHandle);
438
+ }, EVENT_THROTTLE, {
439
+ leading: true,
440
+ trailing: false
441
+ }), []);
541
442
 
542
- // Use the discrete value and percentage for snapping.
443
+ /**
444
+ * Handles a `keydown` event by recalculating the value/thumb and setting
445
+ * state accordingly.
446
+ */
447
+ const onKeyDown = evt => {
448
+ // Do nothing if component is disabled, or we don't have a valid event
449
+ if (props.disabled || props.readOnly) {
450
+ return;
451
+ }
452
+ const {
453
+ step = 1,
454
+ stepMultiplier = 4
455
+ } = props;
456
+ let delta = 0;
457
+ if (match.matches(evt, [keys.ArrowDown, keys.ArrowLeft])) {
458
+ delta = -step;
459
+ } else if (match.matches(evt, [keys.ArrowUp, keys.ArrowRight])) {
460
+ delta = step;
461
+ } else {
462
+ // Ignore keys we don't want to handle
463
+ return;
464
+ }
465
+
466
+ // If shift was held, account for the stepMultiplier
467
+ if (evt.shiftKey) {
468
+ delta *= stepMultiplier;
469
+ }
470
+ if (hasTwoHandles() && state.activeHandle) {
471
+ const currentValue = state.activeHandle === HandlePosition.LOWER ? state.value : state.valueUpper;
543
472
  const {
544
- discreteValue,
545
- discretePercent
546
- } = this.calcDiscreteValueAndPercent({
547
- leftPercent
473
+ value,
474
+ left
475
+ } = calcValue({
476
+ value: calcValueForDelta(currentValue ?? props.min, delta, props.step)
548
477
  });
549
- return {
550
- value: discreteValue,
551
- left: discretePercent * 100
552
- };
553
- });
554
- _rollupPluginBabelHelpers.defineProperty(this, "calcDistanceToHandle", (handle, clientX) => {
555
- const handleBoundingRect = this.getHandleBoundingRect(handle);
556
- // x co-ordinate of the midpoint.
557
- const handleX = handleBoundingRect.left + handleBoundingRect.width / 2;
558
- return Math.abs(handleX - clientX);
559
- });
560
- /**
561
- * Calculates a new slider value based on the current value, a change delta,
562
- * and a step.
563
- *
564
- * @param currentValue - The starting value from which the slider is moving.
565
- * @param delta - The amount to adjust the current value by.
566
- * @param step - The step. Defaults to `1`.
567
- * @returns The new slider value, rounded to the same number of decimal places
568
- * as the step.
569
- */
570
- _rollupPluginBabelHelpers.defineProperty(this, "calcValueForDelta", (currentValue, delta, step = 1) => {
571
- const base = delta > 0 ? Math.floor(currentValue / step) * step : currentValue;
572
- const newValue = base + delta;
573
- const decimals = (step.toString().split('.')[1] || '').length;
574
- return Number(newValue.toFixed(decimals));
575
- });
576
- /**
577
- * Sets state relevant to the given handle position.
578
- *
579
- * Guards against setting either lower or upper values beyond its counterpart.
580
- */
581
- _rollupPluginBabelHelpers.defineProperty(this, "setValueLeftForHandle", (handle, {
582
- value: newValue,
583
- left: newLeft
584
- }) => {
478
+ setValueLeftForHandle(state.activeHandle, {
479
+ value: nearestStepValue(value),
480
+ left
481
+ });
482
+ } else {
585
483
  const {
586
484
  value,
587
- valueUpper,
485
+ left
486
+ } = calcValue({
487
+ // Ensures custom value from `<input>` won't cause skipping next stepping
488
+ // point with right arrow key, e.g. Typing 51 in `<input>`, moving focus
489
+ // onto the thumb and the hitting right arrow key should yield 52 instead
490
+ // of 54.
491
+ value: calcValueForDelta(state.value, delta, props.step)
492
+ });
493
+ setState({
494
+ value: nearestStepValue(value),
588
495
  left,
589
- leftUpper
590
- } = this.state;
591
- if (handle === HandlePosition.LOWER) {
592
- // Don't allow higher than the upper handle.
593
- this.setState({
594
- value: valueUpper && newValue > valueUpper ? valueUpper : newValue,
595
- left: valueUpper && newValue > valueUpper ? leftUpper : newLeft,
596
- isValid: true
496
+ isValid: true
497
+ });
498
+ }
499
+ setState({
500
+ correctedValue: null,
501
+ correctedPosition: null
502
+ });
503
+ };
504
+
505
+ /**
506
+ * Provides the two-way binding for the input field of the Slider. It also
507
+ * Handles a change to the input field by recalculating the value/thumb and
508
+ * setting state accordingly.
509
+ */
510
+ const onChangeInput = evt => {
511
+ // Do nothing if component is disabled
512
+ if (props.disabled || props.readOnly) {
513
+ return;
514
+ }
515
+
516
+ // Do nothing if we have no valid event, target, or value
517
+ if (!evt || !('target' in evt) || typeof evt.target.value !== 'string') {
518
+ return;
519
+ }
520
+
521
+ // Avoid calling calcValue for invalid numbers, but still update the state.
522
+ const activeHandle = evt.target.dataset.handlePosition ?? HandlePosition.LOWER;
523
+ const targetValue = Number.parseFloat(evt.target.value);
524
+ if (hasTwoHandles()) {
525
+ if (isNaN(targetValue)) {
526
+ setValueForHandle(activeHandle, evt.target.value);
527
+ } else if (isValidValueForPosition({
528
+ handle: activeHandle,
529
+ value: targetValue,
530
+ min: props.min,
531
+ max: props.max
532
+ })) {
533
+ processNewInputValue(evt.target);
534
+ } else {
535
+ setValueForHandle(activeHandle, targetValue);
536
+ }
537
+ } else {
538
+ if (isNaN(targetValue)) {
539
+ // TODO: Address this error
540
+ //
541
+ // @ts-expect-error - Passing a string to something that expects a
542
+ // number.
543
+ setState({
544
+ value: evt.target.value
597
545
  });
546
+ } else if (isValidValue({
547
+ value: targetValue,
548
+ min: props.min,
549
+ max: props.max
550
+ })) {
551
+ processNewInputValue(evt.target);
598
552
  } else {
599
- this.setState({
600
- valueUpper: value && newValue < value ? value : newValue,
601
- leftUpper: value && newValue < value ? left : newLeft,
602
- isValidUpper: true
553
+ setState({
554
+ value: targetValue
603
555
  });
604
556
  }
557
+ }
558
+ };
559
+
560
+ /**
561
+ * Checks for validity of input value after clicking out of the input. It also
562
+ * Handles state change to isValid state.
563
+ */
564
+ const onBlurInput = evt => {
565
+ // Do nothing if we have no valid event, target, or value
566
+ if (!evt || !('target' in evt) || typeof evt.target.value !== 'string') {
567
+ return;
568
+ }
569
+ const {
570
+ value: targetValue
571
+ } = evt.target;
572
+ processNewInputValue(evt.target);
573
+ props.onBlur?.({
574
+ value: targetValue,
575
+ handlePosition: evt.target.dataset.handlePosition
605
576
  });
606
- _rollupPluginBabelHelpers.defineProperty(this, "setValueForHandle", (handle, value) => {
607
- if (handle === HandlePosition.LOWER) {
608
- this.setState({
609
- value,
610
- isValid: true
577
+ };
578
+ const onInputKeyDown = evt => {
579
+ // Do nothing if component is disabled, or we don't have a valid event.
580
+ if (props.disabled || props.readOnly || !(evt.target instanceof HTMLInputElement)) {
581
+ return;
582
+ }
583
+
584
+ // Do nothing if we have no valid event, target, or value.
585
+ if (!evt || !('target' in evt) || typeof evt.target.value !== 'string') {
586
+ return;
587
+ }
588
+ if (match.matches(evt, [keys.Enter])) {
589
+ processNewInputValue(evt.target);
590
+ }
591
+ };
592
+ const processNewInputValue = input => {
593
+ setState({
594
+ correctedValue: null,
595
+ correctedPosition: null
596
+ });
597
+ const targetValue = Number.parseFloat(input.value);
598
+ const validity = !isNaN(targetValue);
599
+
600
+ // When there are two handles, we'll also have the data-handle-position
601
+ // attribute to consider the other value before settling on the validity to
602
+ // set.
603
+ const handlePosition = input.dataset.handlePosition;
604
+ if (handlePosition === HandlePosition.LOWER) {
605
+ setState({
606
+ isValid: validity
607
+ });
608
+ } else if (handlePosition === HandlePosition.UPPER) {
609
+ setState({
610
+ isValidUpper: validity
611
+ });
612
+ }
613
+ setState({
614
+ isValid: validity
615
+ });
616
+ if (validity) {
617
+ const adjustedValue = handlePosition ? getAdjustedValueForPosition({
618
+ handle: handlePosition,
619
+ value: targetValue,
620
+ min: props.min,
621
+ max: props.max
622
+ }) : getAdjustedValue({
623
+ value: targetValue,
624
+ min: props.min,
625
+ max: props.max
626
+ });
627
+ if (adjustedValue !== targetValue) {
628
+ setState({
629
+ correctedValue: targetValue.toString(),
630
+ correctedPosition: handlePosition ?? null
611
631
  });
612
632
  } else {
613
- this.setState({
614
- valueUpper: value,
615
- isValidUpper: true
633
+ setState({
634
+ correctedValue: null,
635
+ correctedPosition: null
616
636
  });
617
637
  }
618
- });
619
- _rollupPluginBabelHelpers.defineProperty(this, "isValidValueForPosition", ({
620
- handle,
621
- value: newValue,
622
- min,
623
- max
624
- }) => {
625
638
  const {
626
639
  value,
627
- valueUpper
628
- } = this.state;
629
- if (!this.isValidValue({
630
- value: newValue,
631
- min,
632
- max
633
- })) {
634
- return false;
635
- }
636
- if (handle === HandlePosition.LOWER) {
637
- return !valueUpper || newValue <= valueUpper;
638
- } else if (handle === HandlePosition.UPPER) {
639
- return !value || newValue >= value;
640
+ left
641
+ } = calcValue({
642
+ value: adjustedValue,
643
+ useRawValue: true
644
+ });
645
+ if (handlePosition) {
646
+ setValueLeftForHandle(handlePosition, {
647
+ value: nearestStepValue(value),
648
+ left
649
+ });
650
+ } else {
651
+ setState({
652
+ value,
653
+ left
654
+ });
640
655
  }
641
- return false;
642
- });
643
- _rollupPluginBabelHelpers.defineProperty(this, "isValidValue", ({
644
- value,
645
- min,
646
- max
647
- }) => {
648
- return !(value < min || value > max);
649
- });
650
- _rollupPluginBabelHelpers.defineProperty(this, "getAdjustedValueForPosition", ({
651
- handle,
652
- value: newValue,
656
+ }
657
+ };
658
+ const calcLeftPercent = ({
659
+ clientX,
660
+ value,
661
+ range
662
+ }) => {
663
+ // TODO: Delete the optional chaining operator after `getBoundingClientRect`.
664
+ const boundingRect = elementRef.current?.getBoundingClientRect?.();
665
+ let width = boundingRect ? boundingRect.right - boundingRect.left : 0;
666
+
667
+ // Enforce a minimum width of at least 1 for calculations
668
+ if (width <= 0) {
669
+ width = 1;
670
+ }
671
+
672
+ // If a clientX is specified, use it to calculate the leftPercent. If not,
673
+ // use the provided value to calculate it instead.
674
+ if (clientX) {
675
+ const leftOffset = state.isRtl ? (boundingRect?.right ?? 0) - clientX : clientX - (boundingRect?.left ?? 0);
676
+ return leftOffset / width;
677
+ } else if (value !== null && typeof value !== 'undefined' && range) {
678
+ // Prevent NaN calculation if the range is 0.
679
+ return range === 0 ? 0 : (value - props.min) / range;
680
+ }
681
+ // We should never end up in this scenario, but in case we do, and to
682
+ // re-assure Typescript, return 0.
683
+ return 0;
684
+ };
685
+
686
+ /**
687
+ * Calculates the discrete value (snapped to the nearest step) along
688
+ * with the corresponding handle position percentage.
689
+ */
690
+ const calcDiscreteValueAndPercent = ({
691
+ leftPercent
692
+ }) => {
693
+ const {
694
+ step = 1,
653
695
  min,
654
696
  max
655
- }) => {
656
- const {
657
- value,
658
- valueUpper
659
- } = this.state;
660
- newValue = this.getAdjustedValue({
661
- value: newValue,
662
- min,
663
- max
664
- });
697
+ } = props;
698
+ const numSteps = Math.floor((max - min) / step) + ((max - min) % step === 0 ? 1 : 2);
699
+ /** Index of the step that corresponds to `leftPercent`. */
700
+ const stepIndex = Math.round(leftPercent * (numSteps - 1));
701
+ const discreteValue = stepIndex === numSteps - 1 ? max : min + step * stepIndex;
702
+ /** Percentage corresponding to the step index. */
703
+ const discretePercent = stepIndex / (numSteps - 1);
704
+ return {
705
+ discreteValue,
706
+ discretePercent
707
+ };
708
+ };
665
709
 
666
- // Next adjust to the opposite handle.
667
- if (handle === HandlePosition.LOWER && valueUpper) {
668
- newValue = newValue > valueUpper ? valueUpper : newValue;
669
- } else if (handle === HandlePosition.UPPER && value) {
670
- newValue = newValue < value ? value : newValue;
671
- }
672
- return newValue;
673
- });
674
- _rollupPluginBabelHelpers.defineProperty(this, "getAdjustedValue", ({
710
+ /**
711
+ * Calculates the slider's value and handle position based on either a
712
+ * mouse/touch event or an explicit value.
713
+ */
714
+ const calcValue = ({
715
+ clientX,
716
+ value,
717
+ useRawValue
718
+ }) => {
719
+ const range = props.max - props.min;
720
+ const leftPercentRaw = calcLeftPercent({
721
+ clientX,
675
722
  value,
676
- min,
677
- max
678
- }) => {
679
- if (value < min) {
680
- value = min;
681
- }
682
- if (value > max) {
683
- value = max;
684
- }
685
- return value;
723
+ range
686
724
  });
687
- /**
688
- * Get the bounding rect for the requested handles' DOM element.
689
- *
690
- * If the bounding rect is not available, a new, empty DOMRect is returned.
691
- */
692
- _rollupPluginBabelHelpers.defineProperty(this, "getHandleBoundingRect", handle => {
693
- let boundingRect;
694
- if (handle === HandlePosition.LOWER) {
695
- boundingRect = this.thumbRef.current?.getBoundingClientRect();
696
- } else {
697
- boundingRect = this.thumbRefUpper.current?.getBoundingClientRect();
698
- }
699
- return boundingRect ?? new DOMRect();
725
+ /** `leftPercentRaw` clamped between 0 and 1. */
726
+ const leftPercent = clamp.clamp(leftPercentRaw, 0, 1);
727
+ if (useRawValue) {
728
+ return {
729
+ value,
730
+ left: leftPercent * 100
731
+ };
732
+ }
733
+
734
+ // Use the discrete value and percentage for snapping.
735
+ const {
736
+ discreteValue,
737
+ discretePercent
738
+ } = calcDiscreteValueAndPercent({
739
+ leftPercent
700
740
  });
701
- this.thumbRef = /*#__PURE__*/React.createRef();
702
- this.thumbRefUpper = /*#__PURE__*/React.createRef();
703
- this.filledTrackRef = /*#__PURE__*/React.createRef();
704
- }
741
+ return {
742
+ value: discreteValue,
743
+ left: discretePercent * 100
744
+ };
745
+ };
746
+ const calcDistanceToHandle = (handle, clientX) => {
747
+ const handleBoundingRect = getHandleBoundingRect(handle);
748
+ /** x-coordinate of the midpoint. */
749
+ const handleX = handleBoundingRect.left + handleBoundingRect.width / 2;
750
+ return Math.abs(handleX - clientX);
751
+ };
705
752
 
706
753
  /**
707
- * Sets up initial slider position and value in response to component mount.
754
+ * Calculates a new slider value based on the current value, a change delta,
755
+ * and a step.
756
+ *
757
+ * @param currentValue - The starting value from which the slider is moving.
758
+ * @param delta - The amount to adjust the current value by.
759
+ * @param step - The step. Defaults to `1`.
760
+ * @returns The new slider value, rounded to the same number of decimal places
761
+ * as the step.
708
762
  */
709
- componentDidMount() {
710
- if (this.element) {
711
- const isRtl = document?.dir === 'rtl';
712
- if (this.hasTwoHandles()) {
713
- const {
714
- value,
715
- left
716
- } = this.calcValue({
717
- value: this.state.value,
718
- useRawValue: true
719
- });
720
- const {
721
- value: valueUpper,
722
- left: leftUpper
723
- } = this.calcValue({
724
- value: this.state.valueUpper,
725
- useRawValue: true
726
- });
727
- this.setState({
728
- isRtl,
729
- value,
730
- left,
731
- valueUpper,
732
- leftUpper
733
- });
734
- if (this.filledTrackRef.current) {
735
- this.filledTrackRef.current.style.transform = this.state.isRtl ? `translate(${100 - this.state.leftUpper}%, -50%) scaleX(${(this.state.leftUpper - this.state.left) / 100})` : `translate(${this.state.left}%, -50%) scaleX(${(this.state.leftUpper - this.state.left) / 100})`;
736
- }
737
- } else {
738
- const {
739
- value,
740
- left
741
- } = this.calcValue({
742
- value: this.state.value,
743
- useRawValue: true
744
- });
745
- this.setState({
746
- isRtl,
747
- value,
748
- left
749
- });
750
- if (this.filledTrackRef.current) {
751
- this.filledTrackRef.current.style.transform = this.state.isRtl ? `translate(100%, -50%) scaleX(-${this.state.left / 100})` : `translate(0%, -50%) scaleX(${this.state.left / 100})`;
752
- }
753
- }
754
- }
755
- }
763
+ const calcValueForDelta = (currentValue, delta, step = 1) => {
764
+ const base = delta > 0 ? Math.floor(currentValue / step) * step : currentValue;
765
+ const newValue = base + delta;
766
+ // TODO: Why is the logical OR needed here?
767
+ const decimals = (step.toString().split('.')[1] || '').length;
768
+ return Number(newValue.toFixed(decimals));
769
+ };
756
770
 
757
771
  /**
758
- * Handles firing of `onChange` and `onRelease` callbacks to parent in
759
- * response to state changes.
772
+ * Sets state relevant to the given handle position.
760
773
  *
761
- * @param {*} prevProps prevProps
762
- * @param {*} prevState The previous Slider state, used to see if callbacks
763
- * should be called.
774
+ * Guards against setting either lower or upper values beyond its counterpart.
764
775
  */
765
- componentDidUpdate(prevProps, prevState) {
766
- // Fire onChange event handler if present, if there's a usable value, and
767
- // if the value is different from the last one
768
- if (this.hasTwoHandles()) {
769
- if (this.filledTrackRef.current) {
770
- this.filledTrackRef.current.style.transform = this.state.isRtl ? `translate(${100 - this.state.leftUpper}%, -50%) scaleX(${(this.state.leftUpper - this.state.left) / 100})` : `translate(${this.state.left}%, -50%) scaleX(${(this.state.leftUpper - this.state.left) / 100})`;
771
- }
776
+ const setValueLeftForHandle = (handle, {
777
+ value: newValue,
778
+ left: newLeft
779
+ }) => {
780
+ const {
781
+ value,
782
+ valueUpper,
783
+ left,
784
+ leftUpper
785
+ } = state;
786
+ if (handle === HandlePosition.LOWER) {
787
+ // Don't allow higher than the upper handle.
788
+ setState({
789
+ value: valueUpper && newValue > valueUpper ? valueUpper : newValue,
790
+ left: valueUpper && newValue > valueUpper ? leftUpper : newLeft,
791
+ isValid: true
792
+ });
772
793
  } else {
773
- if (this.filledTrackRef.current) {
774
- this.filledTrackRef.current.style.transform = this.state.isRtl ? `translate(100%, -50%) scaleX(-${this.state.left / 100})` : `translate(0%, -50%) scaleX(${this.state.left / 100})`;
775
- }
776
- }
777
- if ((prevState.value !== this.state.value || prevState.valueUpper !== this.state.valueUpper) && typeof this.props.onChange === 'function') {
778
- this.props.onChange({
779
- value: this.state.value,
780
- valueUpper: this.state.valueUpper
794
+ setState({
795
+ valueUpper: value && newValue < value ? value : newValue,
796
+ leftUpper: value && newValue < value ? left : newLeft,
797
+ isValidUpper: true
781
798
  });
782
799
  }
783
-
784
- // Fire onRelease event handler if present and if needed
785
- if (this.state.needsOnRelease && typeof this.props.onRelease === 'function') {
786
- this.props.onRelease({
787
- value: this.state.value,
788
- valueUpper: this.state.valueUpper
800
+ };
801
+ const setValueForHandle = (handle, value) => {
802
+ if (handle === HandlePosition.LOWER) {
803
+ setState({
804
+ // TODO: Address this error
805
+ //
806
+ // @ts-expect-error - Passing a string to something that expects a
807
+ // number.
808
+ value,
809
+ isValid: true
789
810
  });
790
- // Reset the flag
791
- this.setState({
792
- needsOnRelease: false
811
+ } else {
812
+ setState({
813
+ // TODO: Address this error
814
+ //
815
+ // @ts-expect-error - Passing a string to something that expects a
816
+ // number.
817
+ valueUpper: value,
818
+ isValidUpper: true
793
819
  });
794
820
  }
821
+ };
822
+ const isValidValueForPosition = ({
823
+ handle,
824
+ value: newValue,
825
+ min,
826
+ max
827
+ }) => {
828
+ const {
829
+ value,
830
+ valueUpper
831
+ } = state;
832
+ if (!isValidValue({
833
+ value: newValue,
834
+ min,
835
+ max
836
+ })) {
837
+ return false;
838
+ }
839
+ if (handle === HandlePosition.LOWER) {
840
+ return !valueUpper || newValue <= valueUpper;
841
+ } else if (handle === HandlePosition.UPPER) {
842
+ return !value || newValue >= value;
843
+ }
844
+ return false;
845
+ };
846
+ const isValidValue = ({
847
+ value,
848
+ min,
849
+ max
850
+ }) => {
851
+ return !(value < min || value > max);
852
+ };
853
+ const getAdjustedValueForPosition = ({
854
+ handle,
855
+ value: newValueInput,
856
+ min,
857
+ max
858
+ }) => {
859
+ const {
860
+ value,
861
+ valueUpper
862
+ } = state;
863
+ let newValue = getAdjustedValue({
864
+ value: newValueInput,
865
+ min,
866
+ max
867
+ });
795
868
 
796
- // If value from props does not change, do nothing here.
797
- // Otherwise, do prop -> state sync without "value capping".
798
- if (prevProps.value === this.props.value && prevProps.unstable_valueUpper === this.props.unstable_valueUpper && prevProps.max === this.props.max && prevProps.min === this.props.min) {
799
- return;
869
+ // TODO: Just return the value.
870
+ // Next adjust to the opposite handle.
871
+ if (handle === HandlePosition.LOWER && valueUpper) {
872
+ newValue = newValue > valueUpper ? valueUpper : newValue;
873
+ } else if (handle === HandlePosition.UPPER && value) {
874
+ newValue = newValue < value ? value : newValue;
800
875
  }
801
- this.setState(this.calcValue({
802
- value: this.props.value,
803
- useRawValue: true
804
- }));
805
- if (typeof this.props.unstable_valueUpper !== 'undefined') {
806
- const {
807
- value: valueUpper,
808
- left: leftUpper
809
- } = this.calcValue({
810
- value: this.props.unstable_valueUpper,
811
- useRawValue: true
812
- });
813
- this.setState({
814
- valueUpper,
815
- leftUpper
816
- });
817
- } else {
818
- this.setState({
819
- valueUpper: undefined,
820
- leftUpper: undefined
821
- });
876
+ return newValue;
877
+ };
878
+ const getAdjustedValue = ({
879
+ value,
880
+ min,
881
+ max
882
+ }) => {
883
+ // TODO: Just return the value.
884
+ if (value < min) {
885
+ value = min;
822
886
  }
823
- }
887
+ if (value > max) {
888
+ value = max;
889
+ }
890
+ return value;
891
+ };
824
892
 
825
893
  /**
826
- * Rounds a given value to the nearest step defined by the slider's `step`
827
- * prop.
894
+ * Get the bounding rect for the requested handles' DOM element.
828
895
  *
829
- * @param value - The value to adjust to the nearest step. Defaults to `0`.
830
- * @returns The value rounded to the precision determined by the step.
896
+ * If the bounding rect is not available, a new, empty DOMRect is returned.
831
897
  */
832
- nearestStepValue(value = 0) {
833
- const decimals = (this.props.step?.toString().split('.')[1] || '').length;
834
- return Number(value.toFixed(decimals));
835
- }
836
- getClientXFromEvent(event) {
898
+ const getHandleBoundingRect = handle => {
899
+ let boundingRect;
900
+ if (handle === HandlePosition.LOWER) {
901
+ boundingRect = thumbRef.current?.getBoundingClientRect();
902
+ } else {
903
+ boundingRect = thumbRefUpper.current?.getBoundingClientRect();
904
+ }
905
+ return boundingRect ?? new DOMRect();
906
+ };
907
+ const getClientXFromEvent = event => {
837
908
  let clientX;
838
909
  if ('clientX' in event) {
839
910
  clientX = event.clientX;
@@ -841,17 +912,12 @@ class Slider extends React.PureComponent {
841
912
  clientX = event.touches[0].clientX;
842
913
  }
843
914
  return clientX;
844
- }
845
- hasTwoHandles() {
846
- return typeof this.state.valueUpper !== 'undefined';
847
- }
848
-
849
- // syncs invalid state and prop
850
- static getDerivedStateFromProps(props, state) {
915
+ };
916
+ React.useEffect(() => {
851
917
  const {
852
918
  isValid,
853
919
  isValidUpper
854
- } = state;
920
+ } = stateRef.current;
855
921
  const derivedState = {};
856
922
 
857
923
  // Will override state in favor of invalid prop
@@ -862,16 +928,20 @@ class Slider extends React.PureComponent {
862
928
  if (isValid === false) derivedState.isValid = true;
863
929
  if (isValidUpper === false) derivedState.isValidUpper = true;
864
930
  }
865
- return Object.keys(derivedState).length ? derivedState : null;
866
- }
867
- render() {
868
- var _Fragment, _Fragment2, _Fragment3, _Fragment4;
931
+ if (Object.keys(derivedState).length) {
932
+ setState(derivedState);
933
+ }
934
+ }, [props.invalid]);
935
+
936
+ // TODO: Delete this IIFE. It was added to maintain whitespace and to make it clear
937
+ // what exactly has changed.
938
+ return ((_Fragment, _Fragment2, _Fragment3, _Fragment4) => {
869
939
  const {
870
940
  ariaLabelInput,
871
941
  unstable_ariaLabelInputUpper: ariaLabelInputUpper,
872
942
  className,
873
943
  hideTextInput = false,
874
- id = this.inputId = this.inputId ||
944
+ id = inputIdRef.current = inputIdRef.current ||
875
945
  // TODO:
876
946
  // 1. Why isn't `inputId` just set to this value instead of an empty
877
947
  // string?
@@ -887,6 +957,7 @@ class Slider extends React.PureComponent {
887
957
  hideLabel,
888
958
  step = 1,
889
959
  // TODO: Other properties are deleted below. Why isn't this one?
960
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- https://github.com/carbon-design-system/carbon/issues/20071
890
961
  stepMultiplier: _stepMultiplier,
891
962
  inputType = 'number',
892
963
  invalidText,
@@ -900,8 +971,7 @@ class Slider extends React.PureComponent {
900
971
  warnText,
901
972
  translateWithId: t = translateWithId,
902
973
  ...other
903
- } = this.props;
904
- const twoHandles = this.hasTwoHandles();
974
+ } = props;
905
975
  delete other.onRelease;
906
976
  delete other.invalid;
907
977
  delete other.unstable_valueUpper;
@@ -913,12 +983,14 @@ class Slider extends React.PureComponent {
913
983
  correctedValue,
914
984
  correctedPosition,
915
985
  isRtl
916
- } = this.state;
986
+ } = state;
917
987
  const showWarning = !readOnly && warn ||
918
988
  // TODO: https://github.com/carbon-design-system/carbon/issues/18991#issuecomment-2795709637
989
+ // eslint-disable-next-line valid-typeof , no-constant-binary-expression -- https://github.com/carbon-design-system/carbon/issues/20071
919
990
  typeof correctedValue !== null && correctedPosition === HandlePosition.LOWER && isValid;
920
991
  const showWarningUpper = !readOnly && warn ||
921
992
  // TODO: https://github.com/carbon-design-system/carbon/issues/18991#issuecomment-2795709637
993
+ // eslint-disable-next-line valid-typeof, no-constant-binary-expression -- https://github.com/carbon-design-system/carbon/issues/20071
922
994
  typeof correctedValue !== null && correctedPosition === (twoHandles ? HandlePosition.UPPER : HandlePosition.LOWER) && (twoHandles ? isValidUpper : isValid);
923
995
  return /*#__PURE__*/React.createElement(usePrefix.PrefixContext.Consumer, null, prefix => {
924
996
  const labelId = `${id}-label`;
@@ -970,12 +1042,12 @@ class Slider extends React.PureComponent {
970
1042
  }]);
971
1043
  const lowerThumbWrapperProps = {
972
1044
  style: {
973
- insetInlineStart: `${this.state.left}%`
1045
+ insetInlineStart: `${state.left}%`
974
1046
  }
975
1047
  };
976
1048
  const upperThumbWrapperProps = {
977
1049
  style: {
978
- insetInlineStart: `${this.state.leftUpper}%`
1050
+ insetInlineStart: `${state.leftUpper}%`
979
1051
  }
980
1052
  };
981
1053
  return /*#__PURE__*/React.createElement("div", {
@@ -1001,10 +1073,10 @@ class Slider extends React.PureComponent {
1001
1073
  min: min,
1002
1074
  max: max,
1003
1075
  step: step,
1004
- onChange: this.onChange,
1005
- onBlur: this.onBlur,
1006
- onKeyUp: this.props.onInputKeyUp,
1007
- onKeyDown: this.onInputKeyDown,
1076
+ onChange: onChangeInput,
1077
+ onBlur: onBlurInput,
1078
+ onKeyUp: props.onInputKeyUp,
1079
+ onKeyDown: onInputKeyDown,
1008
1080
  "data-invalid": !isValid && !readOnly ? true : null,
1009
1081
  "data-handle-position": HandlePosition.LOWER,
1010
1082
  "aria-invalid": !isValid && !readOnly ? true : undefined,
@@ -1018,11 +1090,11 @@ class Slider extends React.PureComponent {
1018
1090
  }, formatLabel(min, minLabel)), /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({
1019
1091
  className: sliderClasses,
1020
1092
  ref: node => {
1021
- this.element = node;
1093
+ elementRef.current = node;
1022
1094
  },
1023
- onMouseDown: this.onDragStart,
1024
- onTouchStart: this.onDragStart,
1025
- onKeyDown: this.onKeyDown,
1095
+ onMouseDown: onDragStart,
1096
+ onTouchStart: onDragStart,
1097
+ onKeyDown: onKeyDown,
1026
1098
  role: "presentation",
1027
1099
  tabIndex: -1,
1028
1100
  "data-invalid": (twoHandles ? !isValid || !isValidUpper : !isValid) && !readOnly ? true : null
@@ -1042,8 +1114,8 @@ class Slider extends React.PureComponent {
1042
1114
  "aria-valuenow": value,
1043
1115
  "aria-labelledby": twoHandles ? undefined : labelId,
1044
1116
  "aria-label": twoHandles ? ariaLabelInput : undefined,
1045
- ref: this.thumbRef,
1046
- onFocus: () => this.setState({
1117
+ ref: thumbRef,
1118
+ onFocus: () => setState({
1047
1119
  activeHandle: HandlePosition.LOWER
1048
1120
  })
1049
1121
  }, twoHandles && !isRtl ? _Fragment || (_Fragment = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(SliderHandles.LowerHandle, {
@@ -1067,8 +1139,8 @@ class Slider extends React.PureComponent {
1067
1139
  "aria-valuemin": value,
1068
1140
  "aria-valuenow": valueUpper,
1069
1141
  "aria-label": ariaLabelInputUpper,
1070
- ref: this.thumbRefUpper,
1071
- onFocus: () => this.setState({
1142
+ ref: thumbRefUpper,
1143
+ onFocus: () => setState({
1072
1144
  activeHandle: HandlePosition.UPPER
1073
1145
  })
1074
1146
  }, twoHandles && !isRtl ? _Fragment3 || (_Fragment3 = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(SliderHandles.UpperHandle, {
@@ -1082,11 +1154,11 @@ class Slider extends React.PureComponent {
1082
1154
  }))) : undefined)) : null, /*#__PURE__*/React.createElement("div", {
1083
1155
  className: `${prefix}--slider__track`,
1084
1156
  ref: node => {
1085
- this.track = node;
1157
+ trackRef.current = node;
1086
1158
  }
1087
1159
  }), /*#__PURE__*/React.createElement("div", {
1088
1160
  className: `${prefix}--slider__filled-track`,
1089
- ref: this.filledTrackRef
1161
+ ref: filledTrackRef
1090
1162
  })), /*#__PURE__*/React.createElement(Text.Text, {
1091
1163
  className: `${prefix}--slider__range-label`
1092
1164
  }, formatLabel(max, maxLabel)), /*#__PURE__*/React.createElement("div", {
@@ -1104,10 +1176,10 @@ class Slider extends React.PureComponent {
1104
1176
  min: min,
1105
1177
  max: max,
1106
1178
  step: step,
1107
- onChange: this.onChange,
1108
- onBlur: this.onBlur,
1109
- onKeyDown: this.onInputKeyDown,
1110
- onKeyUp: this.props.onInputKeyUp,
1179
+ onChange: onChangeInput,
1180
+ onBlur: onBlurInput,
1181
+ onKeyDown: onInputKeyDown,
1182
+ onKeyUp: props.onInputKeyUp,
1111
1183
  "data-invalid": (twoHandles ? !isValidUpper : !isValid) && !readOnly ? true : null,
1112
1184
  "data-handle-position": twoHandles ? HandlePosition.UPPER : null,
1113
1185
  "aria-invalid": (twoHandles ? !isValidUpper : !isValid) && !readOnly ? true : undefined,
@@ -1130,10 +1202,8 @@ class Slider extends React.PureComponent {
1130
1202
  correctedValue
1131
1203
  })));
1132
1204
  });
1133
- }
1134
- }
1135
- _rollupPluginBabelHelpers.defineProperty(Slider, "contextType", index.FeatureFlagContext);
1136
- _rollupPluginBabelHelpers.defineProperty(Slider, "translationIds", Object.values(translationIds));
1205
+ })();
1206
+ };
1137
1207
  Slider.propTypes = {
1138
1208
  /**
1139
1209
  * The `ariaLabel` for the `<input>`.
@@ -1274,4 +1344,4 @@ Slider.propTypes = {
1274
1344
  warnText: PropTypes.node
1275
1345
  };
1276
1346
 
1277
- exports.default = Slider;
1347
+ exports.Slider = Slider;