@godxjp/ui 21.0.0 → 23.0.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/README.md +4 -4
- package/dist/app/app-provider.js +2 -1
- package/dist/components/data-display/badge.d.ts +28 -1
- package/dist/components/data-display/badge.js +2 -0
- package/dist/components/data-display/data-table.d.ts +18 -2
- package/dist/components/data-display/data-table.js +4 -0
- package/dist/components/data-display/index.d.ts +1 -1
- package/dist/components/data-display/popover.d.ts +19 -1
- package/dist/components/data-display/popover.js +9 -1
- package/dist/components/data-display/progress.d.ts +37 -0
- package/dist/components/data-display/progress.js +57 -5
- package/dist/components/data-display/scroll-area.d.ts +24 -4
- package/dist/components/data-display/scroll-area.js +34 -72
- package/dist/components/data-entry/cascader.js +8 -6
- package/dist/components/data-entry/checkbox.js +2 -0
- package/dist/components/data-entry/choice-hit-target.d.ts +24 -0
- package/dist/components/data-entry/choice-hit-target.js +12 -0
- package/dist/components/data-entry/control-surface.d.ts +8 -0
- package/dist/components/data-entry/control-surface.js +10 -1
- package/dist/components/data-entry/date-picker.d.ts +10 -3
- package/dist/components/data-entry/date-picker.js +503 -238
- package/dist/components/data-entry/form-field.d.ts +1 -1
- package/dist/components/data-entry/form-field.js +7 -3
- package/dist/components/data-entry/form.js +10 -1
- package/dist/components/data-entry/index.d.ts +0 -6
- package/dist/components/data-entry/index.js +0 -6
- package/dist/components/data-entry/label.d.ts +14 -1
- package/dist/components/data-entry/label.js +6 -1
- package/dist/components/data-entry/radio.d.ts +27 -6
- package/dist/components/data-entry/radio.js +89 -43
- package/dist/components/data-entry/search-select.js +226 -89
- package/dist/components/data-entry/select.d.ts +76 -14
- package/dist/components/data-entry/select.js +497 -163
- package/dist/components/data-entry/slider.d.ts +3 -11
- package/dist/components/data-entry/slider.js +582 -93
- package/dist/components/data-entry/switch.d.ts +6 -3
- package/dist/components/data-entry/switch.js +36 -11
- package/dist/components/layout/mobile-shell.d.ts +1 -1
- package/dist/components/layout/mobile-shell.js +2 -0
- package/dist/components/navigation/dropdown-menu.d.ts +11 -3
- package/dist/components/navigation/dropdown-menu.js +190 -15
- package/dist/components/navigation/index.d.ts +0 -3
- package/dist/components/navigation/index.js +0 -78
- package/dist/components/navigation/steps.d.ts +1 -1
- package/dist/components/navigation/steps.js +3 -1
- package/dist/components/navigation/tabs-scroll.d.ts +27 -0
- package/dist/components/navigation/tabs-scroll.js +52 -1
- package/dist/components/navigation/tabs.d.ts +2 -2
- package/dist/components/navigation/tabs.js +88 -23
- package/dist/components/ui/index.d.ts +0 -4
- package/dist/components/ui/index.js +0 -4
- package/dist/components/ui/input-otp.d.ts +1 -1
- package/dist/components/ui/segmented.d.ts +15 -1
- package/dist/components/ui/segmented.js +15 -6
- package/dist/components/ui/tag-input.js +3 -5
- package/dist/i18n/messages/en.json +3 -2
- package/dist/i18n/messages/ja.json +3 -2
- package/dist/i18n/messages/vi.json +3 -2
- package/dist/lib/datetime/picker-format.d.ts +18 -0
- package/dist/lib/datetime/picker-format.js +35 -1
- package/dist/lib/field-a11y.d.ts +12 -0
- package/dist/lib/field-a11y.js +14 -1
- package/dist/lib/select-options.d.ts +21 -0
- package/dist/lib/select-options.js +46 -0
- package/dist/props/components/data-display.prop.d.ts +16 -6
- package/dist/props/components/data-entry.prop.d.ts +503 -129
- package/dist/props/components/index.d.ts +2 -2
- package/dist/props/components/layout.prop.d.ts +12 -1
- package/dist/props/components/navigation.prop.d.ts +93 -1
- package/dist/props/registry.d.ts +79 -16
- package/dist/props/registry.js +85 -15
- package/dist/props/vocabulary/data.prop.d.ts +12 -0
- package/dist/props/vocabulary/index.d.ts +2 -2
- package/dist/props/vocabulary/layout.prop.d.ts +11 -0
- package/dist/styles/badge-layout.css +4 -0
- package/dist/styles/card-layout.css +6 -6
- package/dist/styles/control.css +220 -29
- package/dist/styles/data-display-layout.css +94 -23
- package/dist/styles/focus-ring.css +6 -4
- package/dist/styles/fonts.css +88 -4
- package/dist/styles/navigation-layout.css +36 -236
- package/dist/styles/shell-layout.css +149 -139
- package/dist/styles/table-layout.css +41 -3
- package/dist/tokens/components/control.css +4 -0
- package/dist/tokens/components/data-display.css +9 -5
- package/dist/tokens/components/navigation.css +9 -5
- package/dist/tokens/components/scroll-area.css +7 -0
- package/dist/tokens/components/segmented.css +0 -2
- package/dist/tokens/components/shell.css +2 -0
- package/dist/tokens/components/table.css +3 -0
- package/dist/tokens/foundation.css +7 -0
- package/docs/COMPONENTS.md +14 -14
- package/docs/CONSUMER-RULES.md +24 -1
- package/docs/CUSTOMER-THEMING.md +7 -1
- package/docs/FRAME-COVERAGE-REPORT.md +5 -11
- package/docs/TOKENS.md +65 -0
- package/docs/data-display/badge.tsx +37 -0
- package/docs/data-display/data-table/index.tsx +45 -1
- package/docs/data-display/popover.tsx +43 -5
- package/docs/data-display/progress.tsx +28 -0
- package/docs/data-display/scroll-area.tsx +51 -45
- package/docs/data-entry/calendar.tsx +2 -2
- package/docs/data-entry/date-picker.tsx +144 -5
- package/docs/data-entry/form/examples/invoice-form.tsx +2 -2
- package/docs/data-entry/form-field/examples/a11y-contract.tsx +3 -5
- package/docs/data-entry/form.tsx +4 -4
- package/docs/data-entry/input-otp.tsx +5 -2
- package/docs/data-entry/number-input.tsx +31 -0
- package/docs/data-entry/segmented.tsx +143 -2
- package/docs/data-entry/select-matrix.tsx +1 -2
- package/docs/data-entry/select.tsx +108 -3
- package/docs/data-entry/slider.tsx +125 -47
- package/docs/feedback/dialog.tsx +1 -2
- package/docs/feedback/sheet.tsx +1 -2
- package/docs/layout/app-shell-states.tsx +143 -0
- package/docs/layout/mobile-shell.tsx +5 -0
- package/docs/navigation/dropdown-menu.tsx +75 -4
- package/docs/navigation/tabs.tsx +149 -0
- package/docs/roadmap/antd-parity.md +35 -34
- package/docs/roadmap/parity-audit-data-entry.md +196 -172
- package/docs/roadmap/parity-audit-layout-navigation-general.md +304 -310
- package/docs/roadmap/parity-backlog.md +8 -10
- package/docs/showcase/acme-portal.tsx +7 -0
- package/package.json +28 -64
- package/scripts/ui-audit.mjs +18 -5
- package/scripts/visual-audit-rules.mjs +0 -7
- package/scripts/visual-audit.mjs +6 -27
- package/dist/components/data-entry/date-range-picker.d.ts +0 -11
- package/dist/components/data-entry/date-range-picker.js +0 -349
- package/dist/components/data-entry/month-picker.d.ts +0 -10
- package/dist/components/data-entry/month-picker.js +0 -241
- package/dist/components/data-entry/month-range-picker.d.ts +0 -10
- package/dist/components/data-entry/month-range-picker.js +0 -301
- package/dist/components/navigation/context-menu.d.ts +0 -21
- package/dist/components/navigation/context-menu.js +0 -149
- package/dist/components/navigation/menubar.d.ts +0 -21
- package/dist/components/navigation/menubar.js +0 -136
- package/dist/components/navigation/navigation-menu.d.ts +0 -10
- package/dist/components/navigation/navigation-menu.js +0 -91
- package/dist/components/ui/context-menu.d.ts +0 -1
- package/dist/components/ui/context-menu.js +0 -2
- package/dist/components/ui/date-range-picker.d.ts +0 -1
- package/dist/components/ui/date-range-picker.js +0 -2
- package/dist/components/ui/menubar.d.ts +0 -1
- package/dist/components/ui/menubar.js +0 -2
- package/dist/components/ui/navigation-menu.d.ts +0 -1
- package/dist/components/ui/navigation-menu.js +0 -2
- package/docs/FRAME-A11Y-CI.md +0 -349
- package/docs/data-entry/date-range-picker.tsx +0 -175
- package/docs/data-entry/month-picker.tsx +0 -101
- package/docs/data-entry/month-range-picker.tsx +0 -115
- package/docs/navigation/context-menu.tsx +0 -128
- package/docs/navigation/menubar.tsx +0 -141
- package/docs/navigation/navigation-menu.tsx +0 -158
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import * as SwitchPrimitive from "@radix-ui/react-switch";
|
|
3
2
|
export type { SwitchProp, SwitchProp as SwitchProps } from "../../props/components/data-entry.prop.js";
|
|
4
|
-
export declare const Switch: React.ForwardRefExoticComponent<Omit<
|
|
3
|
+
export declare const Switch: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref">, "checked" | "defaultChecked" | "onChange" | "value"> & {
|
|
4
|
+
checked?: boolean;
|
|
5
|
+
defaultChecked?: boolean;
|
|
6
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
7
|
+
required?: boolean;
|
|
5
8
|
size?: "sm" | "md";
|
|
6
9
|
loading?: boolean;
|
|
7
10
|
checkedChildren?: React.ReactNode;
|
|
8
11
|
unCheckedChildren?: React.ReactNode;
|
|
9
|
-
} & React.RefAttributes<
|
|
12
|
+
} & React.RefAttributes<HTMLLabelElement>>;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import
|
|
4
|
+
import { Switch as AriaSwitch } from "react-aria-components";
|
|
5
5
|
import { Loader2 } from "lucide-react";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
-
import { useFieldIdentity } from "../../lib/field-a11y.js";
|
|
7
|
+
import { useFieldIdentity, useMirroredInputAttributes } from "../../lib/field-a11y.js";
|
|
8
|
+
import { withOwnHitTarget } from "./choice-hit-target.js";
|
|
8
9
|
const Switch = React.forwardRef(
|
|
9
10
|
({
|
|
10
11
|
className,
|
|
@@ -16,6 +17,8 @@ const Switch = React.forwardRef(
|
|
|
16
17
|
loading = false,
|
|
17
18
|
checkedChildren,
|
|
18
19
|
unCheckedChildren,
|
|
20
|
+
disabled,
|
|
21
|
+
required,
|
|
19
22
|
...props
|
|
20
23
|
}, ref) => {
|
|
21
24
|
const identity = useFieldIdentity({
|
|
@@ -34,19 +37,43 @@ const Switch = React.forwardRef(
|
|
|
34
37
|
}
|
|
35
38
|
onCheckedChange?.(next);
|
|
36
39
|
};
|
|
40
|
+
const ownField = props["data-field"];
|
|
41
|
+
const fieldKey = ownField ?? identity["data-field"];
|
|
42
|
+
const invalid = props["aria-invalid"];
|
|
43
|
+
const isInvalid = invalid !== void 0 && invalid !== false && invalid !== "false";
|
|
44
|
+
const inputRef = React.useRef(null);
|
|
45
|
+
useMirroredInputAttributes(inputRef, {
|
|
46
|
+
"aria-invalid": isInvalid ? "true" : void 0,
|
|
47
|
+
"aria-busy": loading ? "true" : void 0,
|
|
48
|
+
"aria-disabled": loading ? "true" : void 0,
|
|
49
|
+
// react-aria's `Switch` Omits `isRequired`, and a switch is never the target of native
|
|
50
|
+
// constraint validation in this library — the form layer owns that. The prop is accepted
|
|
51
|
+
// for shape and announced through `aria-required`.
|
|
52
|
+
"aria-required": required ? "true" : void 0,
|
|
53
|
+
"data-field": fieldKey
|
|
54
|
+
});
|
|
55
|
+
const state = isChecked ? "checked" : "unchecked";
|
|
37
56
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38
57
|
resolvedName ? /* @__PURE__ */ jsx("input", { type: "hidden", name: resolvedName, value: isChecked ? "1" : "0", readOnly: true }) : null,
|
|
39
58
|
/* @__PURE__ */ jsxs(
|
|
40
|
-
|
|
59
|
+
AriaSwitch,
|
|
41
60
|
{
|
|
61
|
+
...props,
|
|
42
62
|
ref,
|
|
63
|
+
inputRef,
|
|
43
64
|
"data-slot": "switch",
|
|
44
65
|
"data-size": size,
|
|
66
|
+
"data-state": state,
|
|
45
67
|
"data-loading": loading ? "true" : void 0,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
68
|
+
isSelected: isChecked,
|
|
69
|
+
isDisabled: disabled,
|
|
70
|
+
onChange: handleCheckedChange,
|
|
71
|
+
onKeyDown: (event) => {
|
|
72
|
+
if (event.key !== "Enter") return;
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
handleCheckedChange(!isChecked);
|
|
75
|
+
},
|
|
76
|
+
render: (domProps) => /* @__PURE__ */ jsx("label", { ...domProps, children: withOwnHitTarget(domProps.children) }),
|
|
50
77
|
className: cn(
|
|
51
78
|
// `.ui-switch:disabled, .ui-switch[data-disabled]` in styles/control.css already
|
|
52
79
|
// declares both and reads --disabled-opacity. The utility was layered after
|
|
@@ -56,11 +83,9 @@ const Switch = React.forwardRef(
|
|
|
56
83
|
"peer ui-switch shadow-xs transition-all outline-none",
|
|
57
84
|
className
|
|
58
85
|
),
|
|
59
|
-
...props,
|
|
60
|
-
"data-field": identity["data-field"] ?? props["data-field"],
|
|
61
86
|
children: [
|
|
62
87
|
checkedChildren != null || unCheckedChildren != null ? /* @__PURE__ */ jsx("span", { "data-slot": "switch-content", className: "ui-switch-content", "aria-hidden": "true", children: isChecked ? checkedChildren : unCheckedChildren }) : null,
|
|
63
|
-
/* @__PURE__ */ jsx(
|
|
88
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "switch-thumb", "data-state": state, className: "ui-switch-thumb", children: loading ? /* @__PURE__ */ jsx(
|
|
64
89
|
Loader2,
|
|
65
90
|
{
|
|
66
91
|
"data-slot": "switch-spinner",
|
|
@@ -74,7 +99,7 @@ const Switch = React.forwardRef(
|
|
|
74
99
|
] });
|
|
75
100
|
}
|
|
76
101
|
);
|
|
77
|
-
Switch.displayName =
|
|
102
|
+
Switch.displayName = "Switch";
|
|
78
103
|
export {
|
|
79
104
|
Switch
|
|
80
105
|
};
|
|
@@ -18,4 +18,4 @@ export type { MobileShellProp, MobileShellProp as MobileShellProps, } from "../.
|
|
|
18
18
|
* IS the app's primary navigation). They are the same strings in all three locales, and a fourth
|
|
19
19
|
* identical copy under `layout.mobileShell.*` would be three files of duplication to keep in sync.
|
|
20
20
|
*/
|
|
21
|
-
export declare function MobileShell({ statusBar, header, children, actions, tabBar, height, className, }: MobileShellProp): import("react").JSX.Element;
|
|
21
|
+
export declare function MobileShell({ statusBar, header, children, actions, tabBar, height, width, className, }: MobileShellProp): import("react").JSX.Element;
|
|
@@ -9,6 +9,7 @@ function MobileShell({
|
|
|
9
9
|
actions,
|
|
10
10
|
tabBar,
|
|
11
11
|
height = "viewport",
|
|
12
|
+
width = "fill",
|
|
12
13
|
className
|
|
13
14
|
}) {
|
|
14
15
|
const { t } = useTranslation();
|
|
@@ -17,6 +18,7 @@ function MobileShell({
|
|
|
17
18
|
{
|
|
18
19
|
"data-slot": "mobile-shell",
|
|
19
20
|
"data-height": height === "viewport" ? void 0 : height,
|
|
21
|
+
"data-width": width === "fill" ? void 0 : width,
|
|
20
22
|
className: cn("ui-mobile-shell", className),
|
|
21
23
|
children: [
|
|
22
24
|
(statusBar !== void 0 || header !== void 0) && /* @__PURE__ */ jsxs("header", { className: "ui-mobile-shell-chrome", "aria-label": t("layout.appShell.headerLabel"), children: [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type MenuItemRenderProps, type PopoverProps, type PopoverRenderProps } from "react-aria-components";
|
|
3
|
-
import type { DropdownMenuPlacementProp } from "../../props/components/navigation.prop.js";
|
|
4
|
-
export type { DropdownMenuPlacementProp } from "../../props/components/navigation.prop.js";
|
|
3
|
+
import type { DropdownMenuPlacementProp, DropdownMenuTriggerActionProp } from "../../props/components/navigation.prop.js";
|
|
4
|
+
export type { DropdownMenuPlacementProp, DropdownMenuTriggerActionProp, } from "../../props/components/navigation.prop.js";
|
|
5
5
|
/**
|
|
6
6
|
* Dịch trạng thái item của RAC sang bộ `data-*` mà Radix phát ra và CSS của kho đang bám.
|
|
7
7
|
*
|
|
@@ -47,9 +47,17 @@ interface DropdownMenuPropsOwn {
|
|
|
47
47
|
* `useLocale`), nên prop này còn trong API vì hợp đồng, nhưng không tự đảo hướng.
|
|
48
48
|
*/
|
|
49
49
|
dir?: "ltr" | "rtl";
|
|
50
|
+
/** Ant Design `trigger`. @see DropdownMenuTriggerActionProp. Default `['click']`. */
|
|
51
|
+
trigger?: readonly DropdownMenuTriggerActionProp[];
|
|
52
|
+
/** Ant Design `disabled` — no gesture opens the menu (antd empties the trigger list). */
|
|
53
|
+
disabled?: boolean;
|
|
54
|
+
/** Ant Design `mouseEnterDelay`, in SECONDS, for `trigger={['hover']}`. Default 0.15. */
|
|
55
|
+
mouseEnterDelay?: number;
|
|
56
|
+
/** Ant Design `mouseLeaveDelay`, in SECONDS. Default 0.1 — long enough to cross the gap. */
|
|
57
|
+
mouseLeaveDelay?: number;
|
|
50
58
|
}
|
|
51
59
|
type DropdownMenuProps = React.PropsWithChildren<DropdownMenuPropsOwn>;
|
|
52
|
-
export declare function DropdownMenu({ children, open, defaultOpen, onOpenChange, modal, dir, }: DropdownMenuProps): React.JSX.Element;
|
|
60
|
+
export declare function DropdownMenu({ children, open, defaultOpen, onOpenChange, modal, dir, trigger, disabled, mouseEnterDelay, mouseLeaveDelay, }: DropdownMenuProps): React.JSX.Element;
|
|
53
61
|
interface DropdownMenuTriggerProps extends React.ComponentPropsWithoutRef<"button"> {
|
|
54
62
|
/** Giao hành vi mở cho phần tử con thay vì `<button>` mặc định — như Radix. */
|
|
55
63
|
asChild?: boolean;
|
|
@@ -12,9 +12,11 @@ import {
|
|
|
12
12
|
OverlayTriggerStateContext,
|
|
13
13
|
Popover,
|
|
14
14
|
Pressable,
|
|
15
|
+
RootMenuTriggerStateContext,
|
|
15
16
|
Separator,
|
|
16
17
|
OverlayArrow,
|
|
17
|
-
SubmenuTrigger
|
|
18
|
+
SubmenuTrigger,
|
|
19
|
+
useLocale
|
|
18
20
|
} from "react-aria-components";
|
|
19
21
|
import { Check, ChevronRight } from "lucide-react";
|
|
20
22
|
import { cn } from "../../lib/utils.js";
|
|
@@ -58,39 +60,201 @@ function selectEvent(name) {
|
|
|
58
60
|
return typeof CustomEvent === "function" ? new CustomEvent(name, { bubbles: false, cancelable: true }) : { defaultPrevented: false, preventDefault() {
|
|
59
61
|
} };
|
|
60
62
|
}
|
|
61
|
-
const
|
|
63
|
+
const DROPDOWN_MENU_DEFAULT_TRIGGER = ["click"];
|
|
64
|
+
const DROPDOWN_MENU_MOUSE_ENTER_DELAY = 0.15;
|
|
65
|
+
const DROPDOWN_MENU_MOUSE_LEAVE_DELAY = 0.1;
|
|
66
|
+
const SECOND_IN_MS = 1e3;
|
|
67
|
+
const DropdownMenuModalContext = React.createContext({
|
|
68
|
+
modal: true,
|
|
69
|
+
contextMenuGesture: false,
|
|
70
|
+
disabled: false,
|
|
71
|
+
hover: null,
|
|
72
|
+
racOwnsContextMenu: false,
|
|
73
|
+
openedByHover: { current: false }
|
|
74
|
+
});
|
|
75
|
+
function clearContextMenuPoint(state) {
|
|
76
|
+
state?.setPoint(null);
|
|
77
|
+
}
|
|
78
|
+
function chainGestureProps(own, incoming) {
|
|
79
|
+
const merged = { ...own };
|
|
80
|
+
for (const [key, handler] of Object.entries(incoming)) {
|
|
81
|
+
const existing = own[key];
|
|
82
|
+
merged[key] = typeof existing === "function" && typeof handler === "function" ? (event) => {
|
|
83
|
+
existing(event);
|
|
84
|
+
if (!event.defaultPrevented) handler(event);
|
|
85
|
+
} : handler;
|
|
86
|
+
}
|
|
87
|
+
return merged;
|
|
88
|
+
}
|
|
89
|
+
function isContextMenuKey(event) {
|
|
90
|
+
return event.key === "ContextMenu" || event.key === "F10" && event.shiftKey;
|
|
91
|
+
}
|
|
62
92
|
function DropdownMenu({
|
|
63
93
|
children,
|
|
64
94
|
open,
|
|
65
95
|
defaultOpen,
|
|
66
96
|
onOpenChange,
|
|
67
97
|
modal = true,
|
|
68
|
-
dir
|
|
98
|
+
dir,
|
|
99
|
+
trigger = DROPDOWN_MENU_DEFAULT_TRIGGER,
|
|
100
|
+
disabled = false,
|
|
101
|
+
mouseEnterDelay = DROPDOWN_MENU_MOUSE_ENTER_DELAY,
|
|
102
|
+
mouseLeaveDelay = DROPDOWN_MENU_MOUSE_LEAVE_DELAY
|
|
69
103
|
}) {
|
|
70
104
|
void dir;
|
|
71
|
-
const
|
|
72
|
-
|
|
105
|
+
const wantsHover = !disabled && trigger.includes("hover");
|
|
106
|
+
const wantsClick = !disabled && trigger.includes("click");
|
|
107
|
+
const wantsContextMenu = !disabled && trigger.includes("contextMenu");
|
|
108
|
+
const racOwnsContextMenu = wantsContextMenu && !wantsClick && !wantsHover;
|
|
109
|
+
const [uncontrolled, setUncontrolled] = React.useState(defaultOpen ?? false);
|
|
110
|
+
const isOpen = open ?? uncontrolled;
|
|
111
|
+
const isOpenRef = React.useRef(isOpen);
|
|
112
|
+
isOpenRef.current = isOpen;
|
|
113
|
+
const openedByHover = React.useRef(false);
|
|
114
|
+
const setOpen = React.useCallback(
|
|
115
|
+
(next) => {
|
|
116
|
+
if (next === isOpenRef.current) return;
|
|
117
|
+
if (next && disabled) return;
|
|
118
|
+
if (!next) openedByHover.current = false;
|
|
119
|
+
if (open === void 0) setUncontrolled(next);
|
|
120
|
+
onOpenChange?.(next);
|
|
121
|
+
},
|
|
122
|
+
[disabled, open, onOpenChange]
|
|
123
|
+
);
|
|
124
|
+
const enterTimer = React.useRef(null);
|
|
125
|
+
const leaveTimer = React.useRef(null);
|
|
126
|
+
React.useEffect(
|
|
127
|
+
() => () => {
|
|
128
|
+
if (enterTimer.current) clearTimeout(enterTimer.current);
|
|
129
|
+
if (leaveTimer.current) clearTimeout(leaveTimer.current);
|
|
130
|
+
},
|
|
131
|
+
[]
|
|
132
|
+
);
|
|
133
|
+
const hover = React.useMemo(() => {
|
|
134
|
+
if (!wantsHover) return null;
|
|
135
|
+
return {
|
|
136
|
+
enter: () => {
|
|
137
|
+
if (leaveTimer.current) clearTimeout(leaveTimer.current);
|
|
138
|
+
if (isOpenRef.current) return;
|
|
139
|
+
enterTimer.current = setTimeout(() => {
|
|
140
|
+
openedByHover.current = true;
|
|
141
|
+
setOpen(true);
|
|
142
|
+
}, mouseEnterDelay * SECOND_IN_MS);
|
|
143
|
+
},
|
|
144
|
+
leave: () => {
|
|
145
|
+
if (enterTimer.current) clearTimeout(enterTimer.current);
|
|
146
|
+
leaveTimer.current = setTimeout(() => setOpen(false), mouseLeaveDelay * SECOND_IN_MS);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}, [wantsHover, mouseEnterDelay, mouseLeaveDelay, setOpen]);
|
|
150
|
+
const options = React.useMemo(
|
|
151
|
+
() => ({
|
|
152
|
+
// A HOVER MENU CANNOT BE MODAL. A modal RAC popover paints a full-bleed underlay the instant
|
|
153
|
+
// it opens; that underlay lands under the pointer, the trigger gets `pointerleave`, and the
|
|
154
|
+
// menu closes before the reader can move onto it. antd's hover dropdown is non-modal for the
|
|
155
|
+
// same reason. Every other mode keeps the caller's `modal`.
|
|
156
|
+
modal: wantsHover ? false : modal,
|
|
157
|
+
contextMenuGesture: wantsContextMenu,
|
|
158
|
+
disabled,
|
|
159
|
+
hover,
|
|
160
|
+
racOwnsContextMenu,
|
|
161
|
+
openedByHover
|
|
162
|
+
}),
|
|
163
|
+
[modal, wantsContextMenu, disabled, hover, racOwnsContextMenu, wantsHover]
|
|
164
|
+
);
|
|
165
|
+
return /* @__PURE__ */ jsx(DropdownMenuModalContext.Provider, { value: options, children: /* @__PURE__ */ jsx(
|
|
166
|
+
MenuTrigger,
|
|
167
|
+
{
|
|
168
|
+
isOpen,
|
|
169
|
+
onOpenChange: setOpen,
|
|
170
|
+
trigger: racOwnsContextMenu ? "contextMenu" : "press",
|
|
171
|
+
children
|
|
172
|
+
}
|
|
173
|
+
) });
|
|
73
174
|
}
|
|
74
175
|
function DropdownMenuTrigger({ asChild, children, ...props }) {
|
|
75
176
|
const state = React.useContext(OverlayTriggerStateContext);
|
|
177
|
+
const menuState = React.useContext(
|
|
178
|
+
RootMenuTriggerStateContext
|
|
179
|
+
);
|
|
180
|
+
const { contextMenuGesture, disabled, hover, racOwnsContextMenu } = React.useContext(DropdownMenuModalContext);
|
|
76
181
|
const dataState = state?.isOpen ? "open" : "closed";
|
|
182
|
+
const wantsContextMenu = contextMenuGesture;
|
|
183
|
+
const isDisabled = disabled || props.disabled;
|
|
184
|
+
const { direction } = useLocale();
|
|
185
|
+
const openAtTriggerBox = (element) => {
|
|
186
|
+
const rect = element.getBoundingClientRect();
|
|
187
|
+
menuState?.setPoint({ x: direction === "rtl" ? rect.right : rect.left, y: rect.bottom });
|
|
188
|
+
menuState?.open("first");
|
|
189
|
+
};
|
|
190
|
+
const gestureProps = {};
|
|
191
|
+
if (wantsContextMenu && !isDisabled) {
|
|
192
|
+
gestureProps.onKeyDown = (event) => {
|
|
193
|
+
if (!isContextMenuKey(event)) return;
|
|
194
|
+
event.preventDefault();
|
|
195
|
+
openAtTriggerBox(event.currentTarget);
|
|
196
|
+
};
|
|
197
|
+
if (!racOwnsContextMenu) {
|
|
198
|
+
gestureProps.onContextMenu = (event) => {
|
|
199
|
+
event.preventDefault();
|
|
200
|
+
menuState?.setPoint({ x: event.clientX, y: event.clientY });
|
|
201
|
+
menuState?.open(null);
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (!racOwnsContextMenu) {
|
|
206
|
+
gestureProps.onPointerDownCapture = () => clearContextMenuPoint(menuState);
|
|
207
|
+
gestureProps.onKeyDownCapture = (event) => {
|
|
208
|
+
if (!isContextMenuKey(event)) clearContextMenuPoint(menuState);
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
if (hover && !isDisabled) {
|
|
212
|
+
gestureProps.onPointerEnter = (event) => {
|
|
213
|
+
if (event.pointerType === "mouse") hover.enter();
|
|
214
|
+
};
|
|
215
|
+
gestureProps.onPointerLeave = (event) => {
|
|
216
|
+
if (event.pointerType === "mouse") hover.leave();
|
|
217
|
+
};
|
|
218
|
+
}
|
|
77
219
|
if (asChild && React.isValidElement(children)) {
|
|
78
|
-
return /* @__PURE__ */ jsx(Pressable, { children: React.cloneElement(children, {
|
|
220
|
+
return /* @__PURE__ */ jsx(Pressable, { isDisabled, children: React.cloneElement(children, {
|
|
79
221
|
"data-slot": "dropdown-menu-trigger",
|
|
80
|
-
"data-state": dataState
|
|
222
|
+
"data-state": dataState,
|
|
223
|
+
// A right click target is usually a region rather than a button, and Shift+F10 needs it
|
|
224
|
+
// focusable — so it is given a tab stop unless the consumer already placed one.
|
|
225
|
+
...wantsContextMenu && children.props.tabIndex === void 0 ? { tabIndex: 0 } : {},
|
|
226
|
+
...chainGestureProps(
|
|
227
|
+
children.props,
|
|
228
|
+
gestureProps
|
|
229
|
+
)
|
|
81
230
|
}) });
|
|
82
231
|
}
|
|
83
232
|
return /* @__PURE__ */ jsx(
|
|
84
233
|
AriaButton,
|
|
85
234
|
{
|
|
86
|
-
...
|
|
87
|
-
|
|
235
|
+
...chainGestureProps(
|
|
236
|
+
props,
|
|
237
|
+
gestureProps
|
|
238
|
+
),
|
|
239
|
+
isDisabled,
|
|
88
240
|
"data-slot": "dropdown-menu-trigger",
|
|
89
241
|
"data-state": dataState,
|
|
90
242
|
children
|
|
91
243
|
}
|
|
92
244
|
);
|
|
93
245
|
}
|
|
246
|
+
function useHoverSurfaceProps() {
|
|
247
|
+
const { hover } = React.useContext(DropdownMenuModalContext);
|
|
248
|
+
if (!hover) return {};
|
|
249
|
+
return {
|
|
250
|
+
onPointerEnter: (event) => {
|
|
251
|
+
if (event.pointerType === "mouse") hover.enter();
|
|
252
|
+
},
|
|
253
|
+
onPointerLeave: (event) => {
|
|
254
|
+
if (event.pointerType === "mouse") hover.leave();
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
}
|
|
94
258
|
function DropdownMenuPortal({ children }) {
|
|
95
259
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
96
260
|
}
|
|
@@ -129,7 +293,7 @@ function DropdownMenuContent({
|
|
|
129
293
|
className,
|
|
130
294
|
side,
|
|
131
295
|
align,
|
|
132
|
-
sideOffset
|
|
296
|
+
sideOffset,
|
|
133
297
|
placement,
|
|
134
298
|
arrow,
|
|
135
299
|
width,
|
|
@@ -144,17 +308,25 @@ function DropdownMenuContent({
|
|
|
144
308
|
void hideWhenDetached;
|
|
145
309
|
void sticky;
|
|
146
310
|
void forceMount;
|
|
147
|
-
const { modal } = React.useContext(DropdownMenuModalContext);
|
|
311
|
+
const { modal, openedByHover } = React.useContext(DropdownMenuModalContext);
|
|
312
|
+
const hoverSurfaceProps = useHoverSurfaceProps();
|
|
313
|
+
const menuState = React.useContext(
|
|
314
|
+
RootMenuTriggerStateContext
|
|
315
|
+
);
|
|
148
316
|
const anchor = placement ? DROPDOWN_MENU_PLACEMENT[placement] : void 0;
|
|
149
317
|
const overlayPortalContainer = useOverlayPortalContainer();
|
|
318
|
+
const pointAnchored = menuState?.point != null;
|
|
319
|
+
const hasExplicitAnchor = placement !== void 0 || side !== void 0 || align !== void 0;
|
|
320
|
+
const resolvedPlacement = hasExplicitAnchor || !pointAnchored ? toPlacement(side ?? anchor?.side, align ?? anchor?.align) : "bottom start";
|
|
321
|
+
const resolvedOffset = sideOffset ?? (pointAnchored && !hasExplicitAnchor ? 0 : 4);
|
|
150
322
|
return /* @__PURE__ */ jsx(DropdownMenuPortal, { children: /* @__PURE__ */ jsxs(
|
|
151
323
|
Popover,
|
|
152
324
|
{
|
|
153
325
|
UNSTABLE_portalContainer: overlayPortalContainer,
|
|
154
326
|
"data-slot": "dropdown-menu-content",
|
|
155
327
|
isNonModal: !modal,
|
|
156
|
-
placement:
|
|
157
|
-
offset:
|
|
328
|
+
placement: resolvedPlacement,
|
|
329
|
+
offset: resolvedOffset,
|
|
158
330
|
crossOffset: alignOffset,
|
|
159
331
|
shouldFlip: avoidCollisions,
|
|
160
332
|
containerPadding: collisionPadding,
|
|
@@ -168,15 +340,16 @@ function DropdownMenuContent({
|
|
|
168
340
|
"div",
|
|
169
341
|
{
|
|
170
342
|
...props,
|
|
343
|
+
...hoverSurfaceProps,
|
|
171
344
|
role: void 0,
|
|
172
345
|
...radixSurfaceState(state),
|
|
173
|
-
"data-align": align ?? anchor?.align ?? "center",
|
|
346
|
+
"data-align": align ?? anchor?.align ?? (pointAnchored && !hasExplicitAnchor ? "start" : "center"),
|
|
174
347
|
"data-width": width
|
|
175
348
|
}
|
|
176
349
|
)
|
|
177
350
|
),
|
|
178
351
|
children: [
|
|
179
|
-
/* @__PURE__ */ jsx(Menu, { shouldFocusWrap: loop, children }),
|
|
352
|
+
/* @__PURE__ */ jsx(Menu, { shouldFocusWrap: loop, autoFocus: openedByHover.current ? false : void 0, children }),
|
|
180
353
|
arrow ? /* @__PURE__ */ jsx(OverlayArrow, { children: /* @__PURE__ */ jsx(
|
|
181
354
|
"svg",
|
|
182
355
|
{
|
|
@@ -388,6 +561,7 @@ function DropdownMenuSubContent({
|
|
|
388
561
|
void hideWhenDetached;
|
|
389
562
|
void sticky;
|
|
390
563
|
const overlayPortalContainer = useOverlayPortalContainer();
|
|
564
|
+
const hoverSurfaceProps = useHoverSurfaceProps();
|
|
391
565
|
return /* @__PURE__ */ jsx(
|
|
392
566
|
Popover,
|
|
393
567
|
{
|
|
@@ -408,6 +582,7 @@ function DropdownMenuSubContent({
|
|
|
408
582
|
"div",
|
|
409
583
|
{
|
|
410
584
|
...props,
|
|
585
|
+
...hoverSurfaceProps,
|
|
411
586
|
role: void 0,
|
|
412
587
|
...radixSurfaceState(state),
|
|
413
588
|
"data-align": align ?? "center"
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
export { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs.js";
|
|
2
|
-
export { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, } from "./context-menu.js";
|
|
3
2
|
export { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationEllipsis, PaginationPrevious, PaginationNext, } from "./pagination.js";
|
|
4
|
-
export { Menubar, MenubarCheckboxItem, MenubarContent, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, } from "./menubar.js";
|
|
5
|
-
export { NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, } from "./navigation-menu.js";
|
|
6
3
|
export { Steps } from "./steps.js";
|
|
7
4
|
export { FilterBar, FilterBarGroup, Toolbar, ToolbarGroup } from "./filter-bar.js";
|
|
8
5
|
export type { FilterBarChipProp, FilterBarChipProps, FilterBarFilterProp, FilterBarFilterProps, FilterBarGroupProp, FilterBarGroupProps, FilterBarOverflowProp, FilterBarProp, FilterBarProps, FilterBarSearchProp, FilterBarSearchProps, ToolbarGroupProps, ToolbarProps, } from "./filter-bar.js";
|
|
@@ -1,20 +1,4 @@
|
|
|
1
1
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs.js";
|
|
2
|
-
import {
|
|
3
|
-
ContextMenu,
|
|
4
|
-
ContextMenuCheckboxItem,
|
|
5
|
-
ContextMenuContent,
|
|
6
|
-
ContextMenuItem,
|
|
7
|
-
ContextMenuLabel,
|
|
8
|
-
ContextMenuPortal,
|
|
9
|
-
ContextMenuRadioGroup,
|
|
10
|
-
ContextMenuRadioItem,
|
|
11
|
-
ContextMenuSeparator,
|
|
12
|
-
ContextMenuShortcut,
|
|
13
|
-
ContextMenuSub,
|
|
14
|
-
ContextMenuSubContent,
|
|
15
|
-
ContextMenuSubTrigger,
|
|
16
|
-
ContextMenuTrigger
|
|
17
|
-
} from "./context-menu.js";
|
|
18
2
|
import {
|
|
19
3
|
Pagination,
|
|
20
4
|
PaginationContent,
|
|
@@ -24,32 +8,6 @@ import {
|
|
|
24
8
|
PaginationPrevious,
|
|
25
9
|
PaginationNext
|
|
26
10
|
} from "./pagination.js";
|
|
27
|
-
import {
|
|
28
|
-
Menubar,
|
|
29
|
-
MenubarCheckboxItem,
|
|
30
|
-
MenubarContent,
|
|
31
|
-
MenubarItem,
|
|
32
|
-
MenubarLabel,
|
|
33
|
-
MenubarMenu,
|
|
34
|
-
MenubarRadioGroup,
|
|
35
|
-
MenubarRadioItem,
|
|
36
|
-
MenubarSeparator,
|
|
37
|
-
MenubarShortcut,
|
|
38
|
-
MenubarSub,
|
|
39
|
-
MenubarSubContent,
|
|
40
|
-
MenubarSubTrigger,
|
|
41
|
-
MenubarTrigger
|
|
42
|
-
} from "./menubar.js";
|
|
43
|
-
import {
|
|
44
|
-
NavigationMenu,
|
|
45
|
-
NavigationMenuContent,
|
|
46
|
-
NavigationMenuIndicator,
|
|
47
|
-
NavigationMenuItem,
|
|
48
|
-
NavigationMenuLink,
|
|
49
|
-
NavigationMenuList,
|
|
50
|
-
NavigationMenuTrigger,
|
|
51
|
-
NavigationMenuViewport
|
|
52
|
-
} from "./navigation-menu.js";
|
|
53
11
|
import { Steps } from "./steps.js";
|
|
54
12
|
import { FilterBar, FilterBarGroup, Toolbar, ToolbarGroup } from "./filter-bar.js";
|
|
55
13
|
import { AppSettingPicker } from "./app-setting-picker.js";
|
|
@@ -74,20 +32,6 @@ import {
|
|
|
74
32
|
export {
|
|
75
33
|
AppSettingPicker,
|
|
76
34
|
AppSettingToggle,
|
|
77
|
-
ContextMenu,
|
|
78
|
-
ContextMenuCheckboxItem,
|
|
79
|
-
ContextMenuContent,
|
|
80
|
-
ContextMenuItem,
|
|
81
|
-
ContextMenuLabel,
|
|
82
|
-
ContextMenuPortal,
|
|
83
|
-
ContextMenuRadioGroup,
|
|
84
|
-
ContextMenuRadioItem,
|
|
85
|
-
ContextMenuSeparator,
|
|
86
|
-
ContextMenuShortcut,
|
|
87
|
-
ContextMenuSub,
|
|
88
|
-
ContextMenuSubContent,
|
|
89
|
-
ContextMenuSubTrigger,
|
|
90
|
-
ContextMenuTrigger,
|
|
91
35
|
DropdownMenu,
|
|
92
36
|
DropdownMenuCheckboxItem,
|
|
93
37
|
DropdownMenuContent,
|
|
@@ -105,28 +49,6 @@ export {
|
|
|
105
49
|
DropdownMenuTrigger,
|
|
106
50
|
FilterBar,
|
|
107
51
|
FilterBarGroup,
|
|
108
|
-
Menubar,
|
|
109
|
-
MenubarCheckboxItem,
|
|
110
|
-
MenubarContent,
|
|
111
|
-
MenubarItem,
|
|
112
|
-
MenubarLabel,
|
|
113
|
-
MenubarMenu,
|
|
114
|
-
MenubarRadioGroup,
|
|
115
|
-
MenubarRadioItem,
|
|
116
|
-
MenubarSeparator,
|
|
117
|
-
MenubarShortcut,
|
|
118
|
-
MenubarSub,
|
|
119
|
-
MenubarSubContent,
|
|
120
|
-
MenubarSubTrigger,
|
|
121
|
-
MenubarTrigger,
|
|
122
|
-
NavigationMenu,
|
|
123
|
-
NavigationMenuContent,
|
|
124
|
-
NavigationMenuIndicator,
|
|
125
|
-
NavigationMenuItem,
|
|
126
|
-
NavigationMenuLink,
|
|
127
|
-
NavigationMenuList,
|
|
128
|
-
NavigationMenuTrigger,
|
|
129
|
-
NavigationMenuViewport,
|
|
130
52
|
Pagination,
|
|
131
53
|
PaginationContent,
|
|
132
54
|
PaginationEllipsis,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { StepsProp } from "../../props/components/navigation.prop.js";
|
|
3
3
|
export type { StepsProp, StepsProp as StepsProps, StepItemProp, StepStatusProp, StepsSeparatorProp, StepsTypeProp, } from "../../props/components/navigation.prop.js";
|
|
4
|
-
export declare function Steps({ items, value: current, defaultValue, status: currentStatus, orientation, type, size, titlePlacement, separator, percent, onValueChange, className, }: StepsProp): React.JSX.Element;
|
|
4
|
+
export declare function Steps({ items, value: current, defaultValue, status: currentStatus, orientation, type, size, titlePlacement, separator, percent, onValueChange, className, ...props }: StepsProp): React.JSX.Element;
|
|
@@ -50,7 +50,8 @@ function Steps({
|
|
|
50
50
|
separator = "chevron",
|
|
51
51
|
percent,
|
|
52
52
|
onValueChange,
|
|
53
|
-
className
|
|
53
|
+
className,
|
|
54
|
+
...props
|
|
54
55
|
}) {
|
|
55
56
|
const { t } = useTranslation();
|
|
56
57
|
const base = defaultValue;
|
|
@@ -69,6 +70,7 @@ function Steps({
|
|
|
69
70
|
"data-type": type,
|
|
70
71
|
className: cn("flex w-full", inline ? "ui-steps-inline" : "ui-steps-list", className),
|
|
71
72
|
"aria-label": t("navigation.steps.ariaLabel"),
|
|
73
|
+
...props,
|
|
72
74
|
children: items.map((item, index) => {
|
|
73
75
|
const absoluteIndex = base + index;
|
|
74
76
|
const stepStatus = resolveStepStatus(absoluteIndex, current, item.status, currentStatus);
|
|
@@ -34,3 +34,30 @@ export declare function syncActiveTabIntoView(list: HTMLElement | null, behavior
|
|
|
34
34
|
* pre-fix behaviour instead of throwing.
|
|
35
35
|
*/
|
|
36
36
|
export declare function useKeepActiveTabVisible(listRef: React.RefObject<HTMLElement | null>): void;
|
|
37
|
+
/**
|
|
38
|
+
* The values of the triggers that are NOT fully inside the strip's scrollport, in document order.
|
|
39
|
+
*
|
|
40
|
+
* Pure apart from the two rect reads — `values` is the `items` array's own order, and the triggers
|
|
41
|
+
* are matched to it by INDEX rather than by DOM id: `TabsTrigger` hands its `value` to React Aria
|
|
42
|
+
* as the collection KEY, and the rendered `id` attribute is RAC-generated, so the element carries
|
|
43
|
+
* no readable handle back to the item it came from.
|
|
44
|
+
*
|
|
45
|
+
* This is the measurement behind `overflow="menu"`. It is separated from the hook below so it can
|
|
46
|
+
* be exercised on plain numbers — jsdom lays nothing out, so the only honest unit assertions about
|
|
47
|
+
* it are the ones that hand it real geometry.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveHiddenTabValues(list: HTMLElement, values: readonly string[]): string[];
|
|
50
|
+
/**
|
|
51
|
+
* Keeps `onChange` fed with the values currently out of the scrollport, recomputing on the two
|
|
52
|
+
* things that can move them: the strip resizing (a viewport change, a font swap, a tab added or
|
|
53
|
+
* removed) and the strip scrolling (the user swiping, or `useKeepActiveTabVisible` re-pinning a
|
|
54
|
+
* trigger).
|
|
55
|
+
*
|
|
56
|
+
* `values` is joined into the effect key rather than passed as a dependency, so a consumer that
|
|
57
|
+
* rebuilds its `items` array on every render does not re-arm the observers on every render.
|
|
58
|
+
*
|
|
59
|
+
* The first measurement ALWAYS reports, even when nothing is hidden. Suppressing it looks harmless
|
|
60
|
+
* and is not: on a remount the local `last` resets while the caller's state does not, so a strip
|
|
61
|
+
* that had overflowed and then stopped would keep a stale menu forever.
|
|
62
|
+
*/
|
|
63
|
+
export declare function useTabsOverflowValues(listRef: React.RefObject<HTMLElement | null>, values: readonly string[] | undefined, onChange: (hidden: string[]) => void): void;
|