@react-md/core 6.2.1 → 6.3.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 (153) hide show
  1. package/dist/datetime/NativeDateField.d.ts +24 -0
  2. package/dist/datetime/NativeDateField.js +63 -0
  3. package/dist/datetime/NativeDateField.js.map +1 -0
  4. package/dist/datetime/NativeTimeField.d.ts +26 -0
  5. package/dist/datetime/NativeTimeField.js +63 -0
  6. package/dist/datetime/NativeTimeField.js.map +1 -0
  7. package/dist/datetime/useDateField.d.ts +120 -0
  8. package/dist/datetime/useDateField.js +35 -0
  9. package/dist/datetime/useDateField.js.map +1 -0
  10. package/dist/datetime/useTimeField.d.ts +124 -0
  11. package/dist/datetime/useTimeField.js +65 -0
  12. package/dist/datetime/useTimeField.js.map +1 -0
  13. package/dist/datetime/utils.d.ts +34 -0
  14. package/dist/datetime/utils.js +27 -0
  15. package/dist/datetime/utils.js.map +1 -0
  16. package/dist/draggable/utils.d.ts +3 -6
  17. package/dist/draggable/utils.js.map +1 -1
  18. package/dist/expansion-panel/ExpansionList.js +1 -1
  19. package/dist/expansion-panel/ExpansionList.js.map +1 -1
  20. package/dist/expansion-panel/useExpansionList.d.ts +2 -7
  21. package/dist/expansion-panel/useExpansionList.js.map +1 -1
  22. package/dist/form/FormMessage.js +3 -1
  23. package/dist/form/FormMessage.js.map +1 -1
  24. package/dist/form/FormMessageContainer.d.ts +2 -1
  25. package/dist/form/FormMessageContainer.js +3 -2
  26. package/dist/form/FormMessageContainer.js.map +1 -1
  27. package/dist/form/FormMessageCounter.d.ts +3 -2
  28. package/dist/form/FormMessageCounter.js +5 -2
  29. package/dist/form/FormMessageCounter.js.map +1 -1
  30. package/dist/form/Listbox.d.ts +3 -10
  31. package/dist/form/Listbox.js +8 -27
  32. package/dist/form/Listbox.js.map +1 -1
  33. package/dist/form/ListboxProvider.d.ts +17 -0
  34. package/dist/form/ListboxProvider.js +33 -1
  35. package/dist/form/ListboxProvider.js.map +1 -1
  36. package/dist/form/NativeSelect.js +1 -0
  37. package/dist/form/NativeSelect.js.map +1 -1
  38. package/dist/form/TextArea.js +1 -0
  39. package/dist/form/TextArea.js.map +1 -1
  40. package/dist/form/TextField.js +1 -0
  41. package/dist/form/TextField.js.map +1 -1
  42. package/dist/form/_form-message.scss +13 -0
  43. package/dist/form/_text-field.scss +12 -3
  44. package/dist/form/formMessageContainerStyles.d.ts +7 -0
  45. package/dist/form/formMessageContainerStyles.js +4 -2
  46. package/dist/form/formMessageContainerStyles.js.map +1 -1
  47. package/dist/form/sliderUtils.d.ts +3 -7
  48. package/dist/form/sliderUtils.js.map +1 -1
  49. package/dist/form/types.d.ts +13 -0
  50. package/dist/form/types.js.map +1 -1
  51. package/dist/form/useCombobox.d.ts +6 -2
  52. package/dist/form/useCombobox.js +8 -9
  53. package/dist/form/useCombobox.js.map +1 -1
  54. package/dist/form/useFormReset.d.ts +4 -1
  55. package/dist/form/useFormReset.js +9 -4
  56. package/dist/form/useFormReset.js.map +1 -1
  57. package/dist/form/useNumberField.d.ts +5 -5
  58. package/dist/form/useNumberField.js +10 -2
  59. package/dist/form/useNumberField.js.map +1 -1
  60. package/dist/form/useSelectCombobox.js +2 -2
  61. package/dist/form/useSelectCombobox.js.map +1 -1
  62. package/dist/form/useTextField.d.ts +76 -59
  63. package/dist/form/useTextField.js +7 -1
  64. package/dist/form/useTextField.js.map +1 -1
  65. package/dist/interaction/utils.d.ts +14 -0
  66. package/dist/interaction/utils.js +23 -12
  67. package/dist/interaction/utils.js.map +1 -1
  68. package/dist/menu/MenuBar.js +1 -1
  69. package/dist/menu/MenuBar.js.map +1 -1
  70. package/dist/menu/MenuItemTextField.d.ts +1 -2
  71. package/dist/menu/MenuItemTextField.js.map +1 -1
  72. package/dist/menu/MenuWidget.js +3 -2
  73. package/dist/menu/MenuWidget.js.map +1 -1
  74. package/dist/movement/constants.d.ts +10 -0
  75. package/dist/movement/constants.js +20 -4
  76. package/dist/movement/constants.js.map +1 -1
  77. package/dist/movement/types.d.ts +59 -10
  78. package/dist/movement/types.js.map +1 -1
  79. package/dist/movement/useKeyboardMovementProvider.d.ts +5 -1
  80. package/dist/movement/useKeyboardMovementProvider.js +171 -73
  81. package/dist/movement/useKeyboardMovementProvider.js.map +1 -1
  82. package/dist/tabs/useTabList.js +1 -1
  83. package/dist/tabs/useTabList.js.map +1 -1
  84. package/dist/test-utils/drag.d.ts +6 -9
  85. package/dist/transition/useCarousel.d.ts +2 -2
  86. package/dist/transition/useCarousel.js.map +1 -1
  87. package/dist/tree/Tree.js +1 -1
  88. package/dist/tree/Tree.js.map +1 -1
  89. package/dist/tree/useTreeMovement.d.ts +2 -1
  90. package/dist/tree/useTreeMovement.js +2 -1
  91. package/dist/tree/useTreeMovement.js.map +1 -1
  92. package/dist/types.d.ts +14 -0
  93. package/dist/types.js.map +1 -1
  94. package/dist/utils/getMiddleOfRange.d.ts +2 -3
  95. package/dist/utils/getMiddleOfRange.js.map +1 -1
  96. package/dist/utils/getPercentage.d.ts +2 -9
  97. package/dist/utils/getPercentage.js +1 -1
  98. package/dist/utils/getPercentage.js.map +1 -1
  99. package/dist/utils/getRangeSteps.d.ts +2 -3
  100. package/dist/utils/getRangeSteps.js +0 -3
  101. package/dist/utils/getRangeSteps.js.map +1 -1
  102. package/dist/utils/nearest.d.ts +2 -3
  103. package/dist/utils/nearest.js +0 -3
  104. package/dist/utils/nearest.js.map +1 -1
  105. package/dist/utils/trigonometry.d.ts +31 -0
  106. package/dist/utils/trigonometry.js +25 -0
  107. package/dist/utils/trigonometry.js.map +1 -0
  108. package/dist/window-splitter/useWindowSplitter.d.ts +1 -1
  109. package/dist/window-splitter/useWindowSplitter.js.map +1 -1
  110. package/package.json +1 -1
  111. package/src/datetime/NativeDateField.tsx +92 -0
  112. package/src/datetime/NativeTimeField.tsx +94 -0
  113. package/src/datetime/useDateField.ts +193 -0
  114. package/src/datetime/useTimeField.ts +233 -0
  115. package/src/datetime/utils.ts +48 -0
  116. package/src/draggable/utils.ts +3 -6
  117. package/src/expansion-panel/ExpansionList.tsx +2 -1
  118. package/src/expansion-panel/useExpansionList.ts +6 -12
  119. package/src/form/FormMessage.tsx +4 -0
  120. package/src/form/FormMessageContainer.tsx +8 -4
  121. package/src/form/FormMessageCounter.tsx +17 -6
  122. package/src/form/Listbox.tsx +18 -46
  123. package/src/form/ListboxProvider.ts +61 -1
  124. package/src/form/NativeSelect.tsx +1 -0
  125. package/src/form/TextArea.tsx +1 -0
  126. package/src/form/TextField.tsx +1 -0
  127. package/src/form/formMessageContainerStyles.ts +10 -2
  128. package/src/form/sliderUtils.ts +3 -7
  129. package/src/form/types.ts +15 -0
  130. package/src/form/useCombobox.ts +15 -10
  131. package/src/form/useFormReset.ts +12 -5
  132. package/src/form/useNumberField.ts +17 -14
  133. package/src/form/useSelectCombobox.ts +2 -2
  134. package/src/form/useTextField.ts +102 -69
  135. package/src/interaction/utils.ts +18 -20
  136. package/src/menu/MenuBar.tsx +1 -1
  137. package/src/menu/MenuItemTextField.tsx +1 -3
  138. package/src/menu/MenuWidget.tsx +4 -2
  139. package/src/movement/constants.ts +26 -4
  140. package/src/movement/types.ts +84 -19
  141. package/src/movement/useKeyboardMovementProvider.ts +209 -95
  142. package/src/tabs/useTabList.ts +1 -1
  143. package/src/test-utils/drag.ts +8 -12
  144. package/src/transition/useCarousel.ts +2 -2
  145. package/src/tree/Tree.tsx +1 -1
  146. package/src/tree/useTreeMovement.ts +4 -0
  147. package/src/types.ts +16 -0
  148. package/src/utils/getMiddleOfRange.ts +2 -3
  149. package/src/utils/getPercentage.ts +3 -11
  150. package/src/utils/getRangeSteps.ts +3 -3
  151. package/src/utils/nearest.ts +3 -3
  152. package/src/utils/trigonometry.ts +46 -0
  153. package/src/window-splitter/useWindowSplitter.ts +3 -2
@@ -2,14 +2,18 @@ import { type HTMLAttributes, forwardRef } from "react";
2
2
 
3
3
  import { type PropsWithRef } from "../types.js";
4
4
  import { FormMessage } from "./FormMessage.js";
5
- import { formMessageContainer } from "./formMessageContainerStyles.js";
5
+ import {
6
+ type FormMessageContainerClassNameOptions,
7
+ formMessageContainer,
8
+ } from "./formMessageContainerStyles.js";
6
9
  import { type FormMessageProps } from "./types.js";
7
10
 
8
11
  /**
9
12
  * @since 2.5.0
10
13
  */
11
14
  export interface FormMessageContainerProps
12
- extends HTMLAttributes<HTMLDivElement> {
15
+ extends HTMLAttributes<HTMLDivElement>,
16
+ FormMessageContainerClassNameOptions {
13
17
  /**
14
18
  * If the extension doesn't actually want to render the `FormMessage`
15
19
  * component, these props are optional. It kind of eliminates the whole
@@ -29,7 +33,7 @@ export const FormMessageContainer = forwardRef<
29
33
  HTMLDivElement,
30
34
  FormMessageContainerProps
31
35
  >(function FormMessageContainer(props, ref) {
32
- const { className, children, messageProps, ...remaining } = props;
36
+ const { className, children, inline, messageProps, ...remaining } = props;
33
37
  if (!messageProps) {
34
38
  return <>{children}</>;
35
39
  }
@@ -38,7 +42,7 @@ export const FormMessageContainer = forwardRef<
38
42
  <div
39
43
  {...remaining}
40
44
  ref={ref}
41
- className={formMessageContainer({ className })}
45
+ className={formMessageContainer({ className, inline })}
42
46
  >
43
47
  {children}
44
48
  <FormMessage {...messageProps} />
@@ -1,4 +1,9 @@
1
- import { type HTMLAttributes, type ReactElement, type ReactNode } from "react";
1
+ import {
2
+ type HTMLAttributes,
3
+ type ReactElement,
4
+ type ReactNode,
5
+ forwardRef,
6
+ } from "react";
2
7
 
3
8
  import { formMessageCounter } from "./formMessageStyles.js";
4
9
 
@@ -44,15 +49,21 @@ export interface FormMessageCounterProps
44
49
  * @see {@link https://react-md.dev/components/form-message | FormMessage Demos}
45
50
  * @see {@link https://react-md.dev/components/text-field | TextField Demos}
46
51
  * @since 2.9.0
52
+ * @since 6.3.0 Supports refs.
47
53
  */
48
- export function FormMessageCounter(
49
- props: FormMessageCounterProps
50
- ): ReactElement {
54
+ export const FormMessageCounter = forwardRef<
55
+ HTMLSpanElement,
56
+ FormMessageCounterProps
57
+ >(function FormMessageCounter(props, ref): ReactElement {
51
58
  const { children, className, ...remaining } = props;
52
59
 
53
60
  return (
54
- <span {...remaining} className={formMessageCounter({ className })}>
61
+ <span
62
+ ref={ref}
63
+ {...remaining}
64
+ className={formMessageCounter({ className })}
65
+ >
55
66
  {children}
56
67
  </span>
57
68
  );
58
- }
69
+ });
@@ -1,21 +1,15 @@
1
- import {
2
- type Dispatch,
3
- type ReactElement,
4
- type ReactNode,
5
- type Ref,
6
- useMemo,
7
- } from "react";
1
+ "use client";
2
+
3
+ import { type ReactElement, type ReactNode, type Ref } from "react";
8
4
 
9
5
  import { Menu, type MenuProps } from "../menu/Menu.js";
10
6
  import { type LabelRequiredForA11y } from "../types.js";
11
- import { ListboxProvider } from "./ListboxProvider.js";
12
- import { type OptionSelectedIconProps } from "./Option.js";
13
-
14
- /**
15
- * @since 6.0.0
16
- * @internal
17
- */
18
- export type ListboxValue = string | number | null | object;
7
+ import {
8
+ ListboxProvider,
9
+ type ListboxProviderOptions,
10
+ type ListboxValue,
11
+ useListboxProvider,
12
+ } from "./ListboxProvider.js";
19
13
 
20
14
  /**
21
15
  * @since 6.0.0
@@ -23,11 +17,8 @@ export type ListboxValue = string | number | null | object;
23
17
  */
24
18
  export interface ListboxProps<Value extends ListboxValue>
25
19
  extends MenuProps,
26
- OptionSelectedIconProps {
20
+ ListboxProviderOptions<Value> {
27
21
  nodeRef?: Ref<HTMLDivElement>;
28
-
29
- value: Value | readonly NonNullable<ListboxValue>[];
30
- setValue: Dispatch<NonNullable<Value>>;
31
22
  children: ReactNode;
32
23
  }
33
24
 
@@ -49,36 +40,17 @@ export function Listbox<T extends ListboxValue>(
49
40
  disableSelectedIcon,
50
41
  ...remaining
51
42
  } = props;
52
- const values = useMemo(() => {
53
- if (Array.isArray(value)) {
54
- return new Set(value);
55
- }
56
-
57
- return new Set([value]);
58
- }, [value]);
59
43
 
60
44
  return (
61
45
  <ListboxProvider
62
- value={useMemo(
63
- () => ({
64
- selectOption: setValue,
65
- isOptionSelected(option) {
66
- return values.has(option);
67
- },
68
- selectedIcon,
69
- unselectedIcon,
70
- selectedIconAfter,
71
- disableSelectedIcon,
72
- }),
73
- [
74
- disableSelectedIcon,
75
- selectedIcon,
76
- selectedIconAfter,
77
- setValue,
78
- unselectedIcon,
79
- values,
80
- ]
81
- )}
46
+ value={useListboxProvider({
47
+ value,
48
+ setValue,
49
+ selectedIcon,
50
+ selectedIconAfter,
51
+ disableSelectedIcon,
52
+ unselectedIcon,
53
+ })}
82
54
  >
83
55
  <Menu {...remaining} ref={nodeRef}>
84
56
  {children}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { createContext, useContext } from "react";
3
+ import { type Dispatch, createContext, useContext, useMemo } from "react";
4
4
 
5
5
  import { type OptionSelectedIconProps } from "./Option.js";
6
6
 
@@ -37,3 +37,63 @@ export function useListboxContext(): ListboxContext {
37
37
 
38
38
  return value;
39
39
  }
40
+
41
+ /**
42
+ * @since 6.0.0
43
+ * @internal
44
+ */
45
+ export type ListboxValue = string | number | null | object;
46
+
47
+ /**
48
+ * @since 6.3.0
49
+ */
50
+ export interface ListboxProviderOptions<Value extends ListboxValue>
51
+ extends OptionSelectedIconProps {
52
+ value: ListboxValue | readonly NonNullable<ListboxValue>[];
53
+ setValue: Dispatch<NonNullable<Value>>;
54
+ }
55
+
56
+ /**
57
+ * @since 6.3.0
58
+ */
59
+ export function useListboxProvider<Value extends ListboxValue>(
60
+ options: ListboxProviderOptions<Value>
61
+ ): ListboxContext {
62
+ const {
63
+ value,
64
+ setValue,
65
+ selectedIconAfter,
66
+ selectedIcon,
67
+ unselectedIcon,
68
+ disableSelectedIcon,
69
+ } = options;
70
+
71
+ const values = useMemo(() => {
72
+ if (Array.isArray(value)) {
73
+ return new Set(value);
74
+ }
75
+
76
+ return new Set([value]);
77
+ }, [value]);
78
+
79
+ return useMemo(
80
+ () => ({
81
+ selectOption: setValue,
82
+ isOptionSelected(option) {
83
+ return values.has(option);
84
+ },
85
+ selectedIcon,
86
+ unselectedIcon,
87
+ selectedIconAfter,
88
+ disableSelectedIcon,
89
+ }),
90
+ [
91
+ disableSelectedIcon,
92
+ selectedIcon,
93
+ selectedIconAfter,
94
+ setValue,
95
+ unselectedIcon,
96
+ values,
97
+ ]
98
+ );
99
+ }
@@ -161,6 +161,7 @@ export const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
161
161
 
162
162
  return (
163
163
  <FormMessageContainer
164
+ inline={inline}
164
165
  {...messageContainerProps}
165
166
  messageProps={
166
167
  messageProps && {
@@ -250,6 +250,7 @@ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
250
250
 
251
251
  return (
252
252
  <FormMessageContainer
253
+ inline={inline}
253
254
  {...messageContainerProps}
254
255
  messageProps={messageProps}
255
256
  >
@@ -165,6 +165,7 @@ export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
165
165
 
166
166
  return (
167
167
  <FormMessageContainer
168
+ inline={inline}
168
169
  {...messageContainerProps}
169
170
  messageProps={
170
171
  messageProps && {
@@ -9,6 +9,14 @@ const styles = bem("rmd-form-message-container");
9
9
  */
10
10
  export interface FormMessageContainerClassNameOptions {
11
11
  className?: string;
12
+
13
+ /**
14
+ * Set to `true` to enable `display: inline-flex; width: auto`.
15
+ *
16
+ * @defaultValue `false`
17
+ * @since 6.3.0
18
+ */
19
+ inline?: boolean;
12
20
  }
13
21
 
14
22
  /**
@@ -17,7 +25,7 @@ export interface FormMessageContainerClassNameOptions {
17
25
  export function formMessageContainer(
18
26
  options: FormMessageContainerClassNameOptions = {}
19
27
  ): string {
20
- const { className } = options;
28
+ const { className, inline } = options;
21
29
 
22
- return cnb(styles(), className);
30
+ return cnb(styles({ inline }), className);
23
31
  }
@@ -6,7 +6,7 @@ import {
6
6
  type DraggableMouseEventHandlers,
7
7
  type DraggableTouchEventHandlers,
8
8
  } from "../draggable/useDraggable.js";
9
- import { type RenameKeysWithPrefix } from "../types.js";
9
+ import { type MinMaxRange, type RenameKeysWithPrefix } from "../types.js";
10
10
  import {
11
11
  type ClientPositionEvent,
12
12
  getClientPosition,
@@ -18,9 +18,7 @@ import { getRangeSteps } from "../utils/getRangeSteps.js";
18
18
  * @since 6.0.0
19
19
  * @internal
20
20
  */
21
- interface JumpOptions {
22
- min: number;
23
- max: number;
21
+ interface JumpOptions extends MinMaxRange {
24
22
  step: number;
25
23
  jump: number | undefined;
26
24
  }
@@ -178,9 +176,7 @@ function getThumbOffset(
178
176
  * @since 6.0.0
179
177
  * @internal
180
178
  */
181
- export interface ThumbOffsetsOptions {
182
- min: number;
183
- max: number;
179
+ export interface ThumbOffsetsOptions extends MinMaxRange {
184
180
  thumb1Value: number;
185
181
  thumb1Dragging: boolean;
186
182
  thumb1DragPercentage: number;
package/src/form/types.ts CHANGED
@@ -255,6 +255,21 @@ export interface FormMessageProps
255
255
  */
256
256
  disableWrap?: boolean;
257
257
 
258
+ /**
259
+ * Optional props to provide to inline counter.
260
+ *
261
+ * @since 6.3.0
262
+ */
263
+ counterProps?: PropsWithRef<HTMLAttributes<HTMLSpanElement>>;
264
+
265
+ /**
266
+ * Optional props to apply to the `<p>` tag that surrounds the `children`.
267
+ * This will not be used if `role="alert"` or `disableWrap={true}`.
268
+ *
269
+ * @since 6.3.0
270
+ */
271
+ messageProps?: PropsWithRef<HTMLAttributes<HTMLParagraphElement>>;
272
+
258
273
  /**
259
274
  * An optional style to apply to the `<p>` tag that surrounds the `children`.
260
275
  * This will not be used if `role="alert"` or `disableWrap={true}`.
@@ -69,7 +69,12 @@ export interface ComboboxKeyboardMovementData<
69
69
  show: () => void;
70
70
  hide: () => void;
71
71
  visible: boolean;
72
- focusLast: NonNullMutableRef<boolean>;
72
+
73
+ /**
74
+ * @since 6.3.0 Renamed from `focusLast` to `focusLastRef` to support the new
75
+ * actions.
76
+ */
77
+ focusLastRef: NonNullMutableRef<boolean>;
73
78
  }
74
79
 
75
80
  /**
@@ -280,7 +285,7 @@ export interface ComboboxMenuProps<PopupEl extends HTMLElement = HTMLDivElement>
280
285
  export interface ComboboxImplementation<
281
286
  ComboboxEl extends HTMLElement = HTMLInputElement,
282
287
  PopupEl extends HTMLElement = HTMLElement,
283
- > extends KeyboardMovementProviderImplementation<ComboboxEl> {
288
+ > extends Omit<KeyboardMovementProviderImplementation<ComboboxEl>, "nodeRef"> {
284
289
  show: () => void;
285
290
  hide: () => void;
286
291
  visible: boolean;
@@ -349,16 +354,17 @@ export function useCombobox<
349
354
 
350
355
  const popupId = useEnsuredId(propPopupId, "combobox-popup");
351
356
  const comboboxId = useEnsuredId(propComboboxId, "combobox");
352
- const [comboboxRef, comboboxRefCallback] = useEnsuredRef(propComboboxRef);
353
357
  const [popupRef, popupRefCallback] = useEnsuredRef(propPopupRef);
354
- const focusLast = useRef(false);
358
+ const focusLastRef = useRef(false);
355
359
  const {
360
+ nodeRef: comboboxRef,
356
361
  movementProps,
357
362
  movementContext,
358
363
  currentFocusIndex,
359
364
  activeDescendantId,
360
365
  setActiveDescendantId,
361
366
  } = useKeyboardMovementProvider<ComboboxEl>({
367
+ ref: propComboboxRef,
362
368
  onFocus,
363
369
  onKeyDown,
364
370
  onClick(event) {
@@ -375,7 +381,7 @@ export function useCombobox<
375
381
  show,
376
382
  hide,
377
383
  visible,
378
- focusLast,
384
+ focusLastRef,
379
385
  });
380
386
  const { event } = movementData;
381
387
  if (event.isPropagationStopped()) {
@@ -406,7 +412,7 @@ export function useCombobox<
406
412
  case "ArrowDown":
407
413
  event.preventDefault();
408
414
  event.stopPropagation();
409
- focusLast.current = event.key === "ArrowUp";
415
+ focusLastRef.current = event.key === "ArrowUp";
410
416
  show();
411
417
  break;
412
418
  case "Enter":
@@ -445,7 +451,7 @@ export function useCombobox<
445
451
  hide,
446
452
  visible,
447
453
  setVisible,
448
- focusLast,
454
+ focusLast: focusLastRef,
449
455
  popupRef,
450
456
  popupProps,
451
457
  comboboxRef,
@@ -456,7 +462,6 @@ export function useCombobox<
456
462
  "aria-expanded": visible,
457
463
  "aria-haspopup": popup,
458
464
  id: comboboxId,
459
- ref: comboboxRefCallback,
460
465
  role: "combobox",
461
466
  },
462
467
  movementProps,
@@ -496,11 +501,11 @@ export function useCombobox<
496
501
 
497
502
  const focusables = getFocusableElements(popup, true);
498
503
  const index = getEnterDefaultFocusedIndex({
499
- focusLast: focusLast.current,
504
+ focusLast: focusLastRef.current,
500
505
  focusables,
501
506
  currentFocusIndex: currentFocusIndex.current,
502
507
  });
503
- focusLast.current = false;
508
+ focusLastRef.current = false;
504
509
  currentFocusIndex.current = index;
505
510
 
506
511
  const option = focusables[index];
@@ -9,12 +9,15 @@ import {
9
9
 
10
10
  /**
11
11
  * @since 6.0.0
12
+ * @since 6.3.0 Added the optional `onReset` callback and updated
13
+ * `defaultValue` to be optional.
12
14
  * @internal
13
15
  */
14
16
  export interface FormResetOptions {
15
17
  form?: string;
16
18
  elementRef: RefObject<ChangeableHTMLElement>;
17
- defaultValue: string;
19
+ onReset?: () => void;
20
+ defaultValue?: string;
18
21
  }
19
22
 
20
23
  /**
@@ -22,11 +25,11 @@ export interface FormResetOptions {
22
25
  * @internal
23
26
  */
24
27
  export function useFormReset(options: FormResetOptions): void {
25
- const { form, elementRef, defaultValue } = options;
28
+ const { form, elementRef, defaultValue, onReset } = options;
26
29
 
27
30
  useEffect(() => {
28
31
  const element = elementRef.current;
29
- if (!element) {
32
+ if (!element || (typeof defaultValue === "undefined" && !onReset)) {
30
33
  return;
31
34
  }
32
35
 
@@ -39,12 +42,16 @@ export function useFormReset(options: FormResetOptions): void {
39
42
  }
40
43
 
41
44
  const handleReset = (): void => {
42
- triggerManualChangeEvent(element, defaultValue);
45
+ if (onReset) {
46
+ onReset();
47
+ } else if (typeof defaultValue !== "undefined") {
48
+ triggerManualChangeEvent(element, defaultValue);
49
+ }
43
50
  };
44
51
 
45
52
  formElement.addEventListener("reset", handleReset);
46
53
  return () => {
47
54
  formElement.removeEventListener("reset", handleReset);
48
55
  };
49
- }, [defaultValue, elementRef, form]);
56
+ }, [defaultValue, elementRef, form, onReset]);
50
57
  }
@@ -4,6 +4,7 @@ import { useCallback, useRef, useState } from "react";
4
4
 
5
5
  import { type UseStateInitializer, type UseStateSetter } from "../types.js";
6
6
  import { withinRange } from "../utils/withinRange.js";
7
+ import { useFormReset } from "./useFormReset.js";
7
8
  import {
8
9
  type ProvidedTextFieldMessageProps,
9
10
  type ProvidedTextFieldProps,
@@ -46,10 +47,7 @@ export interface NumberFieldConstraints {
46
47
  * - Renamed `fixOnBlur` to `updateValueOnBlur`
47
48
  */
48
49
  export interface NumberFieldHookOptions
49
- extends Omit<
50
- TextFieldHookOptions<HTMLInputElement>,
51
- "defaultValue" | "isNumber"
52
- >,
50
+ extends Omit<TextFieldHookOptions, "defaultValue" | "isNumber">,
53
51
  NumberFieldConstraints {
54
52
  /**
55
53
  * @defaultValue `undefined`
@@ -121,24 +119,21 @@ export interface NumberFieldHookState
121
119
 
122
120
  /** @since 2.5.6 */
123
121
  export interface ProvidedNumberFieldProps
124
- extends ProvidedTextFieldProps<HTMLInputElement>,
122
+ extends ProvidedTextFieldProps,
125
123
  NumberFieldConstraints {
126
124
  type: "number";
127
125
  }
128
126
 
129
127
  /** @since 2.5.6 */
130
128
  export interface ProvidedNumberFieldMessageProps
131
- extends ProvidedTextFieldMessageProps<HTMLInputElement>,
129
+ extends ProvidedTextFieldMessageProps,
132
130
  NumberFieldConstraints {
133
131
  type: "number";
134
132
  }
135
133
 
136
134
  /** @since 6.0.0 */
137
135
  export interface NumberFieldImplementation
138
- extends Omit<
139
- TextFieldImplementation<HTMLInputElement>,
140
- "value" | "setState"
141
- > {
136
+ extends Omit<TextFieldImplementation, "value" | "setState"> {
142
137
  value: number | undefined;
143
138
  setState: UseStateSetter<NumberFieldHookState>;
144
139
  fieldProps: ProvidedNumberFieldProps;
@@ -152,10 +147,7 @@ export interface NumberFieldWithMessageImplementation
152
147
 
153
148
  /** @since 6.0.0 */
154
149
  export interface ValidatedNumberFieldImplementation
155
- extends Omit<
156
- ValidatedTextFieldImplementation<HTMLInputElement>,
157
- "value" | "setState"
158
- > {
150
+ extends Omit<ValidatedTextFieldImplementation, "value" | "setState"> {
159
151
  value: number | undefined;
160
152
  setState: UseStateSetter<NumberFieldHookState>;
161
153
  fieldProps: ProvidedNumberFieldProps | ProvidedNumberFieldMessageProps;
@@ -361,10 +353,12 @@ export function useNumberField(
361
353
  min,
362
354
  max,
363
355
  step,
356
+ form,
364
357
  onBlur = noop,
365
358
  onChange = noop,
366
359
  updateValue = "change",
367
360
  updateValueOnBlur = true,
361
+ disableReset,
368
362
  defaultValue,
369
363
  ...textOptions
370
364
  } = options;
@@ -374,6 +368,7 @@ export function useNumberField(
374
368
  const {
375
369
  value: _value,
376
370
  reset: resetTextField,
371
+ fieldRef,
377
372
  fieldProps,
378
373
  setState: setTextFieldState,
379
374
  ...remaining
@@ -381,6 +376,7 @@ export function useNumberField(
381
376
  ...textOptions,
382
377
  isNumber: true,
383
378
  defaultValue: `${number ?? ""}`,
379
+ disableReset: true,
384
380
  onBlur(event) {
385
381
  onBlur(event);
386
382
  if (event.isPropagationStopped()) {
@@ -482,11 +478,18 @@ export function useNumberField(
482
478
  [setTextFieldState]
483
479
  );
484
480
 
481
+ useFormReset({
482
+ form,
483
+ elementRef: fieldRef,
484
+ onReset: disableReset ? undefined : reset,
485
+ });
486
+
485
487
  return {
486
488
  ...remaining,
487
489
  reset,
488
490
  value: number,
489
491
  setState,
492
+ fieldRef,
490
493
  fieldProps: {
491
494
  ...fieldProps,
492
495
  min,
@@ -40,7 +40,7 @@ export function useSelectCombobox<
40
40
  ...comboboxOptions,
41
41
  searchable: true,
42
42
  extendKeyDown(movementData) {
43
- const { event, show, focusLast, visible } = movementData;
43
+ const { event, show, focusLastRef, visible } = movementData;
44
44
  if (visible) {
45
45
  return;
46
46
  }
@@ -51,7 +51,7 @@ export function useSelectCombobox<
51
51
  case "End":
52
52
  event.preventDefault();
53
53
  event.stopPropagation();
54
- focusLast.current = event.key === "End";
54
+ focusLastRef.current = event.key === "End";
55
55
  show();
56
56
  break;
57
57
  }