@trackunit/react-components 2.10.24 → 2.10.27-alpha-7557f71cc7a.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/index.cjs.js +450 -287
- package/index.esm.js +451 -288
- package/package.json +6 -6
- package/src/components/Menu/MenuContent/MenuContent.d.ts +9 -1
- package/src/components/Menu/MenuContent/MenuContentContext.d.ts +23 -0
- package/src/components/Menu/MenuContent/compactFloatingListRefs.d.ts +18 -0
- package/src/components/Menu/MenuContent/useMenuContentState.d.ts +23 -0
- package/src/components/Menu/MenuItem/MenuItem.d.ts +4 -3
- package/src/components/Menu/MenuItem/useCloseWhenScrolledOut.d.ts +21 -0
- package/src/components/Menu/MenuItem/useMenuItemBehavior.d.ts +38 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-components",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.27-alpha-7557f71cc7a.0",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"migrations": "./migrations.json",
|
|
@@ -14,16 +14,16 @@
|
|
|
14
14
|
"@floating-ui/react": "^0.26.25",
|
|
15
15
|
"string-ts": "^2.0.0",
|
|
16
16
|
"tailwind-merge": "^2.0.0",
|
|
17
|
-
"@trackunit/ui-design-tokens": "1.15.
|
|
18
|
-
"@trackunit/css-class-variance-utilities": "1.14.
|
|
19
|
-
"@trackunit/shared-utils": "1.16.
|
|
20
|
-
"@trackunit/ui-icons": "1.14.
|
|
17
|
+
"@trackunit/ui-design-tokens": "1.15.13-alpha-7557f71cc7a.0",
|
|
18
|
+
"@trackunit/css-class-variance-utilities": "1.14.23-alpha-7557f71cc7a.0",
|
|
19
|
+
"@trackunit/shared-utils": "1.16.26-alpha-7557f71cc7a.0",
|
|
20
|
+
"@trackunit/ui-icons": "1.14.22-alpha-7557f71cc7a.0",
|
|
21
21
|
"es-toolkit": "^1.39.10",
|
|
22
22
|
"@tanstack/react-virtual": "^3.14.3",
|
|
23
23
|
"dequal": "^2.0.3",
|
|
24
24
|
"fflate": "^0.8.2",
|
|
25
25
|
"zod": "^3.25.76",
|
|
26
|
-
"@trackunit/i18n-library-translation": "2.4.
|
|
26
|
+
"@trackunit/i18n-library-translation": "2.4.32-alpha-7557f71cc7a.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"react": "^19.0.0",
|
|
@@ -29,6 +29,11 @@ export interface MenuContentProps extends CommonProps, Styleable, Refable<HTMLDi
|
|
|
29
29
|
* Callback triggered when selected items change.
|
|
30
30
|
*/
|
|
31
31
|
onSelectionChange?: (selected: Array<string>) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Accessible name for the `role="menu"` node. Prefer this (or `aria-labelledby` via the trigger)
|
|
34
|
+
* when the menu is not named by surrounding chrome.
|
|
35
|
+
*/
|
|
36
|
+
"aria-label"?: string;
|
|
32
37
|
}
|
|
33
38
|
/**
|
|
34
39
|
* MenuContent (formerly MenuList) is a popover menu that appears above all other content on the page. It offers a
|
|
@@ -36,6 +41,9 @@ export interface MenuContentProps extends CommonProps, Styleable, Refable<HTMLDi
|
|
|
36
41
|
* roving-tabindex Up/Down navigation (wrapping), Home/End, typeahead, and — via `MenuItem`'s `submenu` prop —
|
|
37
42
|
* nested submenu entry/exit.
|
|
38
43
|
*
|
|
44
|
+
* Items join this menu themselves via `FloatingList` + `useListItem`, so wrapping components do not hide them
|
|
45
|
+
* from the keyboard loop. Non-item children (search inputs, headings, dividers) render untouched.
|
|
46
|
+
*
|
|
39
47
|
* Typically rendered inside a `Popover` (directly, or as `PopoverContent`'s children), in which case it reads
|
|
40
48
|
* the popover's floating context to power its keyboard navigation. Also works standalone (e.g. inside a
|
|
41
49
|
* `Collapse`, with no ambient `Popover`), falling back to its own local, always-open floating context.
|
|
@@ -93,4 +101,4 @@ export interface MenuContentProps extends CommonProps, Styleable, Refable<HTMLDi
|
|
|
93
101
|
* @param {MenuContentProps} props - The props for the MenuContent component
|
|
94
102
|
* @returns {ReactElement} MenuContent component
|
|
95
103
|
*/
|
|
96
|
-
export declare const MenuContent: ({ "data-testid": dataTestId, className, listClassName, children, isMulti, selectedItems
|
|
104
|
+
export declare const MenuContent: ({ "data-testid": dataTestId, className, listClassName, children, isMulti, selectedItems, onSelectionChange, style, ref, "aria-label": ariaLabel, ...args }: MenuContentProps) => ReactElement;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { HTMLProps } from "react";
|
|
2
|
+
type MenuItemInteractionProps = Omit<HTMLProps<HTMLElement>, "selected" | "active"> & {
|
|
3
|
+
active?: boolean;
|
|
4
|
+
selected?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export interface MenuContentContextValue {
|
|
7
|
+
activeIndex: number | null;
|
|
8
|
+
firstEnabledIndex: number;
|
|
9
|
+
getItemProps: (userProps?: MenuItemInteractionProps) => Record<string, unknown>;
|
|
10
|
+
isMulti: boolean;
|
|
11
|
+
selectedItems: Array<string>;
|
|
12
|
+
handleItemClick: (id: string) => void;
|
|
13
|
+
syncRegisteredList: () => void;
|
|
14
|
+
}
|
|
15
|
+
declare const MenuContentContext: import("react").Context<MenuContentContextValue | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Like `useOptionalPopoverContext`, but for the nearest `MenuContent`.
|
|
18
|
+
* `MenuItem` is used without a menu in places, so a missing ancestor must not throw.
|
|
19
|
+
*
|
|
20
|
+
* @returns {MenuContentContextValue | null} The menu context, or `null` when there is no ancestor `MenuContent`
|
|
21
|
+
*/
|
|
22
|
+
export declare const useOptionalMenuContentContext: () => MenuContentContextValue | null;
|
|
23
|
+
export { MenuContentContext };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MutableRefObject } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* FloatingList only grows `elementsRef` / `labelsRef`. On unmount, `useListItem` nulls the element
|
|
4
|
+
* but writes the label back, so a removed row stays a live typeahead target on a dead slot.
|
|
5
|
+
* Re-establish both arrays from currently mounted nodes after each commit.
|
|
6
|
+
*
|
|
7
|
+
* @param elementsRef The FloatingList elements array
|
|
8
|
+
* @param labelsRef The FloatingList typeahead labels array, kept in lockstep with `elementsRef`
|
|
9
|
+
*/
|
|
10
|
+
export declare const compactFloatingListRefs: (elementsRef: MutableRefObject<Array<HTMLElement | null>>, labelsRef: MutableRefObject<Array<string | null>>) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Index of the first registered item that is not `aria-disabled`. Used as the initial tab stop
|
|
13
|
+
* when `activeIndex` is still null.
|
|
14
|
+
*
|
|
15
|
+
* @param elementsRef The FloatingList elements array
|
|
16
|
+
* @returns {number} The first enabled index, or `0` when the list has no enabled item
|
|
17
|
+
*/
|
|
18
|
+
export declare const firstEnabledListIndex: (elementsRef: MutableRefObject<Array<HTMLElement | null>>) => number;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useInteractions, useMergeRefs } from "@floating-ui/react";
|
|
2
|
+
import { KeyboardEvent, MutableRefObject, ReactNode, Ref } from "react";
|
|
3
|
+
import { MenuContentContextValue } from "./MenuContentContext";
|
|
4
|
+
export interface UseMenuContentStateProps {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
isMulti: boolean;
|
|
7
|
+
selectedItems?: Array<string>;
|
|
8
|
+
onSelectionChange?: (selected: Array<string>) => void;
|
|
9
|
+
ref?: Ref<HTMLDivElement>;
|
|
10
|
+
}
|
|
11
|
+
export interface UseMenuContentStateResult {
|
|
12
|
+
floatingRef: ReturnType<typeof useMergeRefs<HTMLDivElement>>;
|
|
13
|
+
getFloatingProps: ReturnType<typeof useInteractions>["getFloatingProps"];
|
|
14
|
+
handleKeyDownCapture: (event: KeyboardEvent<HTMLDivElement>) => void;
|
|
15
|
+
listRef: MutableRefObject<Array<HTMLElement | null>>;
|
|
16
|
+
labelsRef: MutableRefObject<Array<string | null>>;
|
|
17
|
+
menuContext: MenuContentContextValue;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Owns MenuContent's list registration, selection, and typeable-child key handling so the
|
|
21
|
+
* component file stays the shell + JSX.
|
|
22
|
+
*/
|
|
23
|
+
export declare const useMenuContentState: ({ children, isMulti, selectedItems: controlledSelectedItems, onSelectionChange, ref, }: UseMenuContentStateProps) => UseMenuContentStateResult;
|
|
@@ -12,12 +12,13 @@ export interface MenuItemProps extends CommonProps, Styleable, Refable<HTMLDivEl
|
|
|
12
12
|
*/
|
|
13
13
|
id?: string;
|
|
14
14
|
/**
|
|
15
|
-
* Label of the menu item
|
|
15
|
+
* Label of the menu item. Also the typeahead string. When `children` is a React node rather than
|
|
16
|
+
* a string, keep `label` set so typeahead still matches this row.
|
|
16
17
|
*/
|
|
17
18
|
label?: string;
|
|
18
19
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
20
|
+
* Custom content that replaces the label visually. Does not replace `label` for typeahead —
|
|
21
|
+
* keep `label` set to the searchable string whenever `children` is not itself a string.
|
|
21
22
|
*/
|
|
22
23
|
children?: ReactNode;
|
|
23
24
|
/**
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { MutableRefObject } from "react";
|
|
2
|
+
export interface UseCloseWhenScrolledOutOptions {
|
|
3
|
+
open: boolean;
|
|
4
|
+
nodeRef: MutableRefObject<HTMLElement | null>;
|
|
5
|
+
returnFocusRef: MutableRefObject<HTMLElement | null>;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A submenu's trigger row commonly lives inside a scrollable `MenuContent` list. Without this, a
|
|
10
|
+
* submenu opened from a row that later scrolls out of view stays open, floating disconnected from
|
|
11
|
+
* any visible row -- and (since nothing else would ever close it) stays that way even once the row
|
|
12
|
+
* scrolls back into view. `IntersectionObserver` (rather than e.g. the `Popover`'s own
|
|
13
|
+
* `ancestorScroll` dismissal) is what lets this react to the row's actual visibility instead of
|
|
14
|
+
* firing on every scroll tick of any ancestor, however small or unrelated to this row -- browsers
|
|
15
|
+
* compute intersection against every ancestor's overflow-clip box, not just an explicit `root`, so
|
|
16
|
+
* this fires as soon as *this* row's clipped out, even if some other list ancestor keeps scrolling.
|
|
17
|
+
* Only observing while `open` (rather than unconditionally) means the effect's own close
|
|
18
|
+
* never re-triggers itself, which is also exactly what keeps the submenu from reopening on its own
|
|
19
|
+
* once the row scrolls back into view -- there's no observer left running to notice that happen.
|
|
20
|
+
*/
|
|
21
|
+
export declare const useCloseWhenScrolledOut: ({ open, nodeRef, returnFocusRef, onClose, }: UseCloseWhenScrolledOutOptions) => void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useMergeRefs } from "@floating-ui/react";
|
|
2
|
+
import { FocusEventHandler, MouseEventHandler, MutableRefObject, PointerEventHandler, ReactNode, Ref } from "react";
|
|
3
|
+
interface UseMenuItemBehaviorProps {
|
|
4
|
+
className?: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
selected: boolean;
|
|
8
|
+
disabled: boolean;
|
|
9
|
+
onClick?: MouseEventHandler<HTMLDivElement>;
|
|
10
|
+
stopPropagation: boolean;
|
|
11
|
+
id?: string;
|
|
12
|
+
tabIndex?: number;
|
|
13
|
+
ref?: Ref<HTMLDivElement>;
|
|
14
|
+
submenu?: ReactNode;
|
|
15
|
+
suffix?: ReactNode;
|
|
16
|
+
onFocus?: FocusEventHandler<HTMLDivElement>;
|
|
17
|
+
onMouseMove?: MouseEventHandler<HTMLDivElement>;
|
|
18
|
+
onPointerLeave?: PointerEventHandler<HTMLDivElement>;
|
|
19
|
+
}
|
|
20
|
+
export interface UseMenuItemBehaviorResult {
|
|
21
|
+
mergedRowRef: ReturnType<typeof useMergeRefs<HTMLDivElement>>;
|
|
22
|
+
mergedTriggerRef: ReturnType<typeof useMergeRefs<HTMLDivElement>>;
|
|
23
|
+
submenuOpen: boolean;
|
|
24
|
+
setSubmenuOpen: (open: boolean) => void;
|
|
25
|
+
returnFocusRef: MutableRefObject<HTMLElement | null>;
|
|
26
|
+
isSelected: boolean;
|
|
27
|
+
resolvedSuffix: ReactNode | undefined;
|
|
28
|
+
listClassName?: string;
|
|
29
|
+
resolvedTabIndex: number;
|
|
30
|
+
interactionProps: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Registers this row with the nearest `MenuContent` (no-op when there isn't one) and resolves the
|
|
34
|
+
* interaction / selection / tabIndex props the row needs. Submenu open state lives here so the
|
|
35
|
+
* scroll-out closer can share it.
|
|
36
|
+
*/
|
|
37
|
+
export declare const useMenuItemBehavior: ({ className, label, children, selected, disabled, onClick, stopPropagation, id, tabIndex, ref, submenu, suffix, onFocus, onMouseMove, onPointerLeave, }: UseMenuItemBehaviorProps) => UseMenuItemBehaviorResult;
|
|
38
|
+
export {};
|