@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.
- package/dist/datetime/NativeDateField.d.ts +24 -0
- package/dist/datetime/NativeDateField.js +63 -0
- package/dist/datetime/NativeDateField.js.map +1 -0
- package/dist/datetime/NativeTimeField.d.ts +26 -0
- package/dist/datetime/NativeTimeField.js +63 -0
- package/dist/datetime/NativeTimeField.js.map +1 -0
- package/dist/datetime/useDateField.d.ts +120 -0
- package/dist/datetime/useDateField.js +35 -0
- package/dist/datetime/useDateField.js.map +1 -0
- package/dist/datetime/useTimeField.d.ts +124 -0
- package/dist/datetime/useTimeField.js +65 -0
- package/dist/datetime/useTimeField.js.map +1 -0
- package/dist/datetime/utils.d.ts +34 -0
- package/dist/datetime/utils.js +27 -0
- package/dist/datetime/utils.js.map +1 -0
- package/dist/draggable/utils.d.ts +3 -6
- package/dist/draggable/utils.js.map +1 -1
- package/dist/expansion-panel/ExpansionList.js +1 -1
- package/dist/expansion-panel/ExpansionList.js.map +1 -1
- package/dist/expansion-panel/useExpansionList.d.ts +2 -7
- package/dist/expansion-panel/useExpansionList.js.map +1 -1
- package/dist/form/FormMessage.js +3 -1
- package/dist/form/FormMessage.js.map +1 -1
- package/dist/form/FormMessageContainer.d.ts +2 -1
- package/dist/form/FormMessageContainer.js +3 -2
- package/dist/form/FormMessageContainer.js.map +1 -1
- package/dist/form/FormMessageCounter.d.ts +3 -2
- package/dist/form/FormMessageCounter.js +5 -2
- package/dist/form/FormMessageCounter.js.map +1 -1
- package/dist/form/Listbox.d.ts +3 -10
- package/dist/form/Listbox.js +8 -27
- package/dist/form/Listbox.js.map +1 -1
- package/dist/form/ListboxProvider.d.ts +17 -0
- package/dist/form/ListboxProvider.js +33 -1
- package/dist/form/ListboxProvider.js.map +1 -1
- package/dist/form/NativeSelect.js +1 -0
- package/dist/form/NativeSelect.js.map +1 -1
- package/dist/form/TextArea.js +1 -0
- package/dist/form/TextArea.js.map +1 -1
- package/dist/form/TextField.js +1 -0
- package/dist/form/TextField.js.map +1 -1
- package/dist/form/_form-message.scss +13 -0
- package/dist/form/_text-field.scss +12 -3
- package/dist/form/formMessageContainerStyles.d.ts +7 -0
- package/dist/form/formMessageContainerStyles.js +4 -2
- package/dist/form/formMessageContainerStyles.js.map +1 -1
- package/dist/form/sliderUtils.d.ts +3 -7
- package/dist/form/sliderUtils.js.map +1 -1
- package/dist/form/types.d.ts +13 -0
- package/dist/form/types.js.map +1 -1
- package/dist/form/useCombobox.d.ts +6 -2
- package/dist/form/useCombobox.js +8 -9
- package/dist/form/useCombobox.js.map +1 -1
- package/dist/form/useFormReset.d.ts +4 -1
- package/dist/form/useFormReset.js +9 -4
- package/dist/form/useFormReset.js.map +1 -1
- package/dist/form/useNumberField.d.ts +5 -5
- package/dist/form/useNumberField.js +10 -2
- package/dist/form/useNumberField.js.map +1 -1
- package/dist/form/useSelectCombobox.js +2 -2
- package/dist/form/useSelectCombobox.js.map +1 -1
- package/dist/form/useTextField.d.ts +76 -59
- package/dist/form/useTextField.js +7 -1
- package/dist/form/useTextField.js.map +1 -1
- package/dist/interaction/utils.d.ts +14 -0
- package/dist/interaction/utils.js +23 -12
- package/dist/interaction/utils.js.map +1 -1
- package/dist/menu/MenuBar.js +1 -1
- package/dist/menu/MenuBar.js.map +1 -1
- package/dist/menu/MenuItemTextField.d.ts +1 -2
- package/dist/menu/MenuItemTextField.js.map +1 -1
- package/dist/menu/MenuWidget.js +3 -2
- package/dist/menu/MenuWidget.js.map +1 -1
- package/dist/movement/constants.d.ts +10 -0
- package/dist/movement/constants.js +20 -4
- package/dist/movement/constants.js.map +1 -1
- package/dist/movement/types.d.ts +59 -10
- package/dist/movement/types.js.map +1 -1
- package/dist/movement/useKeyboardMovementProvider.d.ts +5 -1
- package/dist/movement/useKeyboardMovementProvider.js +171 -73
- package/dist/movement/useKeyboardMovementProvider.js.map +1 -1
- package/dist/tabs/useTabList.js +1 -1
- package/dist/tabs/useTabList.js.map +1 -1
- package/dist/test-utils/drag.d.ts +6 -9
- package/dist/transition/useCarousel.d.ts +2 -2
- package/dist/transition/useCarousel.js.map +1 -1
- package/dist/tree/Tree.js +1 -1
- package/dist/tree/Tree.js.map +1 -1
- package/dist/tree/useTreeMovement.d.ts +2 -1
- package/dist/tree/useTreeMovement.js +2 -1
- package/dist/tree/useTreeMovement.js.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/getMiddleOfRange.d.ts +2 -3
- package/dist/utils/getMiddleOfRange.js.map +1 -1
- package/dist/utils/getPercentage.d.ts +2 -9
- package/dist/utils/getPercentage.js +1 -1
- package/dist/utils/getPercentage.js.map +1 -1
- package/dist/utils/getRangeSteps.d.ts +2 -3
- package/dist/utils/getRangeSteps.js +0 -3
- package/dist/utils/getRangeSteps.js.map +1 -1
- package/dist/utils/nearest.d.ts +2 -3
- package/dist/utils/nearest.js +0 -3
- package/dist/utils/nearest.js.map +1 -1
- package/dist/utils/trigonometry.d.ts +31 -0
- package/dist/utils/trigonometry.js +25 -0
- package/dist/utils/trigonometry.js.map +1 -0
- package/dist/window-splitter/useWindowSplitter.d.ts +1 -1
- package/dist/window-splitter/useWindowSplitter.js.map +1 -1
- package/package.json +1 -1
- package/src/datetime/NativeDateField.tsx +92 -0
- package/src/datetime/NativeTimeField.tsx +94 -0
- package/src/datetime/useDateField.ts +193 -0
- package/src/datetime/useTimeField.ts +233 -0
- package/src/datetime/utils.ts +48 -0
- package/src/draggable/utils.ts +3 -6
- package/src/expansion-panel/ExpansionList.tsx +2 -1
- package/src/expansion-panel/useExpansionList.ts +6 -12
- package/src/form/FormMessage.tsx +4 -0
- package/src/form/FormMessageContainer.tsx +8 -4
- package/src/form/FormMessageCounter.tsx +17 -6
- package/src/form/Listbox.tsx +18 -46
- package/src/form/ListboxProvider.ts +61 -1
- package/src/form/NativeSelect.tsx +1 -0
- package/src/form/TextArea.tsx +1 -0
- package/src/form/TextField.tsx +1 -0
- package/src/form/formMessageContainerStyles.ts +10 -2
- package/src/form/sliderUtils.ts +3 -7
- package/src/form/types.ts +15 -0
- package/src/form/useCombobox.ts +15 -10
- package/src/form/useFormReset.ts +12 -5
- package/src/form/useNumberField.ts +17 -14
- package/src/form/useSelectCombobox.ts +2 -2
- package/src/form/useTextField.ts +102 -69
- package/src/interaction/utils.ts +18 -20
- package/src/menu/MenuBar.tsx +1 -1
- package/src/menu/MenuItemTextField.tsx +1 -3
- package/src/menu/MenuWidget.tsx +4 -2
- package/src/movement/constants.ts +26 -4
- package/src/movement/types.ts +84 -19
- package/src/movement/useKeyboardMovementProvider.ts +209 -95
- package/src/tabs/useTabList.ts +1 -1
- package/src/test-utils/drag.ts +8 -12
- package/src/transition/useCarousel.ts +2 -2
- package/src/tree/Tree.tsx +1 -1
- package/src/tree/useTreeMovement.ts +4 -0
- package/src/types.ts +16 -0
- package/src/utils/getMiddleOfRange.ts +2 -3
- package/src/utils/getPercentage.ts +3 -11
- package/src/utils/getRangeSteps.ts +3 -3
- package/src/utils/nearest.ts +3 -3
- package/src/utils/trigonometry.ts +46 -0
- 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 {
|
|
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 {
|
|
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
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
61
|
+
<span
|
|
62
|
+
ref={ref}
|
|
63
|
+
{...remaining}
|
|
64
|
+
className={formMessageCounter({ className })}
|
|
65
|
+
>
|
|
55
66
|
{children}
|
|
56
67
|
</span>
|
|
57
68
|
);
|
|
58
|
-
}
|
|
69
|
+
});
|
package/src/form/Listbox.tsx
CHANGED
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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 {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
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={
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
+
}
|
package/src/form/TextArea.tsx
CHANGED
package/src/form/TextField.tsx
CHANGED
|
@@ -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
|
}
|
package/src/form/sliderUtils.ts
CHANGED
|
@@ -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}`.
|
package/src/form/useCombobox.ts
CHANGED
|
@@ -69,7 +69,12 @@ export interface ComboboxKeyboardMovementData<
|
|
|
69
69
|
show: () => void;
|
|
70
70
|
hide: () => void;
|
|
71
71
|
visible: boolean;
|
|
72
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
504
|
+
focusLast: focusLastRef.current,
|
|
500
505
|
focusables,
|
|
501
506
|
currentFocusIndex: currentFocusIndex.current,
|
|
502
507
|
});
|
|
503
|
-
|
|
508
|
+
focusLastRef.current = false;
|
|
504
509
|
currentFocusIndex.current = index;
|
|
505
510
|
|
|
506
511
|
const option = focusables[index];
|
package/src/form/useFormReset.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
|
|
54
|
+
focusLastRef.current = event.key === "End";
|
|
55
55
|
show();
|
|
56
56
|
break;
|
|
57
57
|
}
|