@mezzanine-ui/react 1.0.0-beta.2 → 1.0.0-beta.4
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/Anchor/Anchor.d.ts +51 -18
- package/Anchor/Anchor.js +15 -15
- package/Anchor/AnchorGroup.d.ts +34 -0
- package/Anchor/AnchorGroup.js +37 -0
- package/Anchor/AnchorItem.d.ts +30 -0
- package/Anchor/AnchorItem.js +65 -0
- package/Anchor/index.d.ts +2 -0
- package/Anchor/index.js +1 -0
- package/Anchor/utils.d.ts +13 -0
- package/Anchor/utils.js +95 -0
- package/AutoComplete/AutoComplete.d.ts +217 -0
- package/AutoComplete/AutoComplete.js +433 -0
- package/AutoComplete/index.d.ts +2 -0
- package/AutoComplete/index.js +1 -0
- package/AutoComplete/useAutoCompleteCreation.d.ts +33 -0
- package/AutoComplete/useAutoCompleteCreation.js +201 -0
- package/AutoComplete/useAutoCompleteKeyboard.d.ts +31 -0
- package/AutoComplete/useAutoCompleteKeyboard.js +149 -0
- package/AutoComplete/useAutoCompleteSearch.d.ts +16 -0
- package/AutoComplete/useAutoCompleteSearch.js +69 -0
- package/AutoComplete/useCreationTracker.d.ts +17 -0
- package/AutoComplete/useCreationTracker.js +47 -0
- package/Breadcrumb/Breadcrumb.js +16 -21
- package/Breadcrumb/BreadcrumbDropdown.d.ts +11 -0
- package/Breadcrumb/BreadcrumbDropdown.js +22 -0
- package/Breadcrumb/BreadcrumbItem.d.ts +2 -3
- package/Breadcrumb/BreadcrumbItem.js +13 -31
- package/Breadcrumb/BreadcrumbOverflowMenu.d.ts +7 -0
- package/Breadcrumb/BreadcrumbOverflowMenu.js +77 -0
- package/Breadcrumb/BreadcrumbOverflowMenuDropdown.d.ts +11 -0
- package/Breadcrumb/BreadcrumbOverflowMenuDropdown.js +21 -0
- package/Breadcrumb/BreadcrumbOverflowMenuItem.d.ts +3 -0
- package/Breadcrumb/BreadcrumbOverflowMenuItem.js +27 -0
- package/Breadcrumb/typings.d.ts +21 -39
- package/Button/Button.js +13 -11
- package/Button/index.d.ts +1 -1
- package/Button/typings.d.ts +27 -4
- package/Checkbox/index.d.ts +4 -5
- package/Checkbox/index.js +1 -5
- package/ContentHeader/ContentHeader.d.ts +160 -0
- package/ContentHeader/ContentHeader.js +54 -0
- package/ContentHeader/index.d.ts +2 -0
- package/ContentHeader/index.js +1 -0
- package/ContentHeader/utils.d.ts +23 -0
- package/ContentHeader/utils.js +215 -0
- package/Description/Description.d.ts +12 -22
- package/Description/Description.js +4 -24
- package/Dropdown/Dropdown.d.ts +46 -1
- package/Dropdown/Dropdown.js +99 -14
- package/Dropdown/DropdownAction.d.ts +1 -1
- package/Dropdown/DropdownAction.js +1 -4
- package/Dropdown/DropdownItem.d.ts +28 -1
- package/Dropdown/DropdownItem.js +56 -14
- package/Dropdown/DropdownItemCard.d.ts +2 -2
- package/Dropdown/DropdownItemCard.js +20 -16
- package/Dropdown/DropdownStatus.js +29 -0
- package/Dropdown/dropdownKeydownHandler.d.ts +2 -1
- package/Dropdown/dropdownKeydownHandler.js +73 -0
- package/Dropdown/highlightText.js +5 -1
- package/Dropdown/shortcutTextHandler.d.ts +24 -0
- package/Dropdown/shortcutTextHandler.js +171 -0
- package/Empty/Empty.js +2 -1
- package/Empty/icons/EmptyMainNotificationIcon.d.ts +4 -0
- package/Empty/icons/EmptyMainNotificationIcon.js +9 -0
- package/Empty/typings.d.ts +2 -2
- package/FilterArea/Filter.d.ts +32 -0
- package/FilterArea/Filter.js +23 -0
- package/FilterArea/FilterArea.d.ts +58 -0
- package/FilterArea/FilterArea.js +31 -0
- package/FilterArea/FilterLine.d.ts +11 -0
- package/FilterArea/FilterLine.js +13 -0
- package/FilterArea/index.d.ts +6 -0
- package/FilterArea/index.js +3 -0
- package/Form/FormField.js +3 -1
- package/Input/Input.d.ts +35 -7
- package/Input/Input.js +48 -14
- package/Input/index.d.ts +1 -1
- package/Modal/MediaPreviewModal.d.ts +54 -0
- package/Modal/MediaPreviewModal.js +158 -0
- package/Modal/Modal.d.ts +103 -11
- package/Modal/Modal.js +14 -9
- package/Modal/ModalBodyForVerification.d.ts +59 -0
- package/Modal/ModalBodyForVerification.js +99 -0
- package/Modal/ModalControl.d.ts +2 -2
- package/Modal/ModalControl.js +1 -1
- package/Modal/ModalFooter.d.ts +119 -1
- package/Modal/ModalFooter.js +15 -3
- package/Modal/ModalHeader.d.ts +26 -7
- package/Modal/ModalHeader.js +33 -7
- package/Modal/index.d.ts +6 -5
- package/Modal/index.js +2 -2
- package/Modal/useModalContainer.d.ts +12 -3
- package/Modal/useModalContainer.js +28 -6
- package/Navigation/Navigation.d.ts +7 -2
- package/Navigation/Navigation.js +36 -35
- package/Navigation/NavigationHeader.d.ts +4 -0
- package/Navigation/NavigationHeader.js +3 -2
- package/Navigation/NavigationOption.d.ts +8 -3
- package/Navigation/NavigationOption.js +46 -11
- package/Navigation/NavigationOptionCategory.js +1 -0
- package/Navigation/NavigationOverflowMenu.d.ts +6 -0
- package/Navigation/NavigationOverflowMenu.js +90 -0
- package/Navigation/NavigationOverflowMenuOption.d.ts +7 -0
- package/Navigation/NavigationOverflowMenuOption.js +68 -0
- package/Navigation/NavigationUserMenu.d.ts +4 -2
- package/Navigation/NavigationUserMenu.js +13 -5
- package/Navigation/context.d.ts +3 -2
- package/Navigation/useVisibleItems.d.ts +5 -0
- package/Navigation/useVisibleItems.js +54 -0
- package/NotificationCenter/NotificationCenter.d.ts +124 -0
- package/NotificationCenter/NotificationCenter.js +279 -0
- package/NotificationCenter/NotificationCenterDrawer.d.ts +109 -0
- package/NotificationCenter/index.d.ts +3 -0
- package/NotificationCenter/index.js +1 -0
- package/PageFooter/PageFooter.d.ts +19 -9
- package/PageFooter/PageFooter.js +10 -10
- package/PageHeader/PageHeader.d.ts +32 -25
- package/PageHeader/PageHeader.js +49 -43
- package/ResultState/ResultState.d.ts +9 -0
- package/ResultState/ResultState.js +36 -4
- package/Scrollbar/Scrollbar.d.ts +9 -0
- package/Scrollbar/Scrollbar.js +78 -0
- package/Scrollbar/index.d.ts +2 -0
- package/Scrollbar/index.js +1 -0
- package/Scrollbar/typings.d.ts +47 -0
- package/Select/SelectTrigger.js +5 -4
- package/Select/index.d.ts +0 -2
- package/Select/index.js +0 -1
- package/Select/typings.d.ts +6 -1
- package/Selection/Selection.js +1 -1
- package/Selection/SelectionGroup.d.ts +28 -0
- package/Slider/useSlider.js +1 -1
- package/Table/Table.d.ts +2 -120
- package/Table/Table.js +148 -53
- package/Table/TableContext.d.ts +11 -12
- package/Table/components/TableActionsCell.js +12 -4
- package/Table/components/TableBody.js +2 -1
- package/Table/components/TableBulkActions.js +1 -19
- package/Table/components/TableColGroup.d.ts +1 -4
- package/Table/components/TableColGroup.js +15 -16
- package/Table/components/TableCollectableCell.d.ts +17 -0
- package/Table/components/TableCollectableCell.js +54 -0
- package/Table/components/TableDragOrPinHandleCell.d.ts +20 -0
- package/Table/components/TableDragOrPinHandleCell.js +58 -0
- package/Table/components/TableExpandedRow.js +11 -2
- package/Table/components/TableHeader.js +12 -10
- package/Table/components/TableRow.js +38 -13
- package/Table/components/TableSelectionCell.js +1 -1
- package/Table/components/TableToggleableCell.d.ts +16 -0
- package/Table/components/TableToggleableCell.js +51 -0
- package/Table/components/index.d.ts +4 -1
- package/Table/components/index.js +3 -0
- package/Table/hooks/typings.d.ts +18 -4
- package/Table/hooks/useTableExpansion.d.ts +2 -2
- package/Table/hooks/useTableExpansion.js +5 -5
- package/Table/hooks/useTableFixedOffsets.d.ts +6 -2
- package/Table/hooks/useTableFixedOffsets.js +60 -26
- package/Table/hooks/useTableScroll.d.ts +9 -3
- package/Table/hooks/useTableScroll.js +34 -7
- package/Table/hooks/useTableVirtualization.d.ts +2 -1
- package/Table/hooks/useTableVirtualization.js +2 -8
- package/Table/index.d.ts +4 -3
- package/Table/index.js +3 -0
- package/Table/typings.d.ts +172 -0
- package/Table/utils/useTableRowSelection.js +13 -5
- package/Tag/TagGroup.d.ts +3 -0
- package/Tag/index.d.ts +2 -0
- package/Tag/index.js +1 -0
- package/Transition/Slide.d.ts +9 -2
- package/Transition/Slide.js +7 -4
- package/Tree/TreeNode.js +1 -1
- package/Upload/UploadPictureCard.js +1 -1
- package/index.d.ts +37 -21
- package/index.js +25 -11
- package/package.json +6 -4
- package/Modal/ModalActions.d.ts +0 -9
- package/Modal/ModalActions.js +0 -20
- package/Modal/ModalBody.d.ts +0 -7
- package/Modal/ModalBody.js +0 -14
- package/Notification/Notification.d.ts +0 -54
- package/Notification/Notification.js +0 -76
- package/Notification/index.d.ts +0 -3
- package/Notification/index.js +0 -1
- package/PageToolbar/PageToolbar.d.ts +0 -114
- package/PageToolbar/PageToolbar.js +0 -23
- package/PageToolbar/index.d.ts +0 -2
- package/PageToolbar/index.js +0 -1
- package/PageToolbar/utils.d.ts +0 -23
- package/PageToolbar/utils.js +0 -165
- package/Select/AutoComplete.d.ts +0 -107
- package/Select/AutoComplete.js +0 -114
- package/Table/components/TableDragHandleCell.d.ts +0 -11
- package/Table/components/TableDragHandleCell.js +0 -44
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { BackdropProps } from '../Backdrop';
|
|
3
|
+
export interface ModalContainerProps extends Pick<BackdropProps, 'className' | 'container' | 'disableCloseOnBackdropClick' | 'disablePortal' | 'onBackdropClick' | 'onClose' | 'open'> {
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
/**
|
|
6
|
+
* Controls whether to disable closing modal while escape key down.
|
|
7
|
+
* @default false
|
|
8
|
+
*/
|
|
9
|
+
disableCloseOnEscapeKeyDown?: boolean;
|
|
10
|
+
}
|
|
2
11
|
export default function useModalContainer(): {
|
|
3
|
-
Container: import("react").ForwardRefExoticComponent<
|
|
4
|
-
defaultOptions: Pick<
|
|
12
|
+
Container: import("react").ForwardRefExoticComponent<ModalContainerProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
13
|
+
defaultOptions: Pick<ModalContainerProps, "className" | "open" | "disablePortal" | "disableCloseOnBackdropClick" | "disableCloseOnEscapeKeyDown">;
|
|
5
14
|
};
|
|
@@ -1,19 +1,41 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { modalClasses } from '@mezzanine-ui/core/modal';
|
|
3
|
-
import { forwardRef } from 'react';
|
|
4
|
-
import
|
|
3
|
+
import { forwardRef, useState } from 'react';
|
|
4
|
+
import { useDocumentEscapeKeyDown } from '../hooks/useDocumentEscapeKeyDown.js';
|
|
5
|
+
import useTopStack from '../_internal/SlideFadeOverlay/useTopStack.js';
|
|
6
|
+
import Backdrop from '../Backdrop/Backdrop.js';
|
|
7
|
+
import Fade from '../Transition/Fade.js';
|
|
8
|
+
import cx from 'clsx';
|
|
5
9
|
|
|
6
10
|
const defaultOptions = {
|
|
7
11
|
className: modalClasses.overlay,
|
|
8
|
-
direction: 'down',
|
|
9
12
|
disableCloseOnBackdropClick: false,
|
|
10
13
|
disableCloseOnEscapeKeyDown: false,
|
|
11
14
|
disablePortal: false,
|
|
12
15
|
open: false,
|
|
13
16
|
};
|
|
14
|
-
const ModalContainer = forwardRef((props, ref)
|
|
15
|
-
const { className = defaultOptions.className,
|
|
16
|
-
|
|
17
|
+
const ModalContainer = forwardRef(function ModalContainer(props, ref) {
|
|
18
|
+
const { children, className = defaultOptions.className, container, disableCloseOnBackdropClick = defaultOptions.disableCloseOnBackdropClick, disableCloseOnEscapeKeyDown = defaultOptions.disableCloseOnEscapeKeyDown, disablePortal = defaultOptions.disablePortal, onBackdropClick, onClose, open = defaultOptions.open, } = props;
|
|
19
|
+
const [exited, setExited] = useState(true);
|
|
20
|
+
/**
|
|
21
|
+
* Escape keydown close: escape will only close the top modal
|
|
22
|
+
*/
|
|
23
|
+
const checkIsOnTheTop = useTopStack(open);
|
|
24
|
+
useDocumentEscapeKeyDown(() => {
|
|
25
|
+
if (!open || disableCloseOnEscapeKeyDown || !onClose) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
return (event) => {
|
|
29
|
+
if (checkIsOnTheTop()) {
|
|
30
|
+
event.stopPropagation();
|
|
31
|
+
onClose();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}, [disableCloseOnEscapeKeyDown, checkIsOnTheTop, open, onClose]);
|
|
35
|
+
if (!open && exited) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return (jsx(Backdrop, { className: cx(className), container: container, disableCloseOnBackdropClick: disableCloseOnBackdropClick, disablePortal: disablePortal, onBackdropClick: onBackdropClick, onClose: onClose, open: open, role: "presentation", children: jsx(Fade, { in: open, onEntered: () => setExited(false), onExited: () => setExited(true), children: jsx("div", { ref: ref, children: children }) }) }));
|
|
17
39
|
});
|
|
18
40
|
function useModalContainer() {
|
|
19
41
|
return {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
2
|
import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
|
|
3
3
|
import { NavigationOptionProps } from './NavigationOption';
|
|
4
4
|
import { NavigationHeaderProps } from './NavigationHeader';
|
|
5
5
|
import { NavigationFooterProps } from './NavigationFooter';
|
|
6
|
-
|
|
6
|
+
import { NavigationOptionCategoryProps } from './NavigationOptionCategory';
|
|
7
|
+
export type NavigationChild = ReactElement<NavigationFooterProps> | ReactElement<NavigationHeaderProps> | ReactElement<NavigationOptionCategoryProps> | ReactElement<NavigationOptionProps> | null | undefined | false;
|
|
7
8
|
export type NavigationChildren = NavigationChild | NavigationChild[];
|
|
8
9
|
export interface NavigationProps extends Omit<NativeElementPropsWithoutKeyAndRef<'ul'>, 'onClick'> {
|
|
9
10
|
/**
|
|
@@ -19,6 +20,10 @@ export interface NavigationProps extends Omit<NativeElementPropsWithoutKeyAndRef
|
|
|
19
20
|
* @default false (expanded)
|
|
20
21
|
*/
|
|
21
22
|
collapsed?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Whether to show search input
|
|
25
|
+
*/
|
|
26
|
+
filter?: boolean;
|
|
22
27
|
/**
|
|
23
28
|
* Called when collapsed state changes.
|
|
24
29
|
*/
|
package/Navigation/Navigation.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import { forwardRef, useState, useCallback, useMemo, Children, isValidElement
|
|
3
|
+
import { forwardRef, useState, useCallback, useMemo, Children, isValidElement } from 'react';
|
|
4
4
|
import { navigationClasses } from '@mezzanine-ui/core/navigation';
|
|
5
5
|
import NavigationOption from './NavigationOption.js';
|
|
6
6
|
import NavigationHeader from './NavigationHeader.js';
|
|
@@ -9,11 +9,13 @@ import { flattenChildren } from '../utils/flatten-children.js';
|
|
|
9
9
|
import NavigationOptionCategory from './NavigationOptionCategory.js';
|
|
10
10
|
import { NavigationActivatedContext, NavigationOptionLevelContext, navigationOptionLevelContextDefaultValues } from './context.js';
|
|
11
11
|
import { useCurrentPathname } from './useCurrentPathname.js';
|
|
12
|
+
import { useVisibleItems } from './useVisibleItems.js';
|
|
13
|
+
import { NavigationOverflowMenu } from './NavigationOverflowMenu.js';
|
|
12
14
|
import Input from '../Input/Input.js';
|
|
13
15
|
import cx from 'clsx';
|
|
14
16
|
|
|
15
17
|
const Navigation = forwardRef((props, ref) => {
|
|
16
|
-
const { activatedPath, children = [], className, collapsed: collapsedProp,
|
|
18
|
+
const { activatedPath, children = [], className, collapsed: collapsedProp, filter, onCollapseChange, onOptionClick, ...rest } = props;
|
|
17
19
|
const [collapsedState, setCollapsedState] = useState(collapsedProp || false);
|
|
18
20
|
const collapsed = collapsedProp !== null && collapsedProp !== void 0 ? collapsedProp : collapsedState;
|
|
19
21
|
const handleCollapseChange = useCallback((newCollapsed) => {
|
|
@@ -27,11 +29,12 @@ const Navigation = forwardRef((props, ref) => {
|
|
|
27
29
|
}, [onOptionClick]);
|
|
28
30
|
const currentPathname = useCurrentPathname();
|
|
29
31
|
const flattenedChildren = useMemo(() => flattenChildren(children), [children]);
|
|
30
|
-
const { headerComponent, footerComponent,
|
|
32
|
+
const { headerComponent, footerComponent, items, level1Items } = useMemo(() => {
|
|
31
33
|
let headerComponent = null;
|
|
32
34
|
let footerComponent = null;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
const items = [];
|
|
36
|
+
const level1Items = [];
|
|
37
|
+
Children.forEach(flattenedChildren, (child, index) => {
|
|
35
38
|
if (child && isValidElement(child)) {
|
|
36
39
|
switch (child.type) {
|
|
37
40
|
case NavigationHeader: {
|
|
@@ -42,48 +45,46 @@ const Navigation = forwardRef((props, ref) => {
|
|
|
42
45
|
footerComponent = child;
|
|
43
46
|
break;
|
|
44
47
|
}
|
|
45
|
-
case Input: {
|
|
46
|
-
searchInput = cloneElement(child, {
|
|
47
|
-
size: 'sub',
|
|
48
|
-
variant: 'search',
|
|
49
|
-
className: cx(navigationClasses.searchInput, child.props.className),
|
|
50
|
-
});
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
return { headerComponent, footerComponent, searchInput };
|
|
57
|
-
}, [flattenedChildren]);
|
|
58
|
-
const renderItemChildren = useCallback(function renderItemChildrenImpl(parsedChildren) {
|
|
59
|
-
var _a;
|
|
60
|
-
const childArray = Children.map(parsedChildren, (child) => {
|
|
61
|
-
if (child && isValidElement(child)) {
|
|
62
|
-
switch (child.type) {
|
|
63
48
|
case NavigationOptionCategory:
|
|
49
|
+
level1Items.push(...(child.props.children
|
|
50
|
+
? flattenChildren(child.props.children, -1, [
|
|
51
|
+
child.props.title || 'NavigationOptionCategory:' + index,
|
|
52
|
+
])
|
|
53
|
+
: []));
|
|
54
|
+
items.push(child);
|
|
55
|
+
break;
|
|
64
56
|
case NavigationOption: {
|
|
65
|
-
|
|
57
|
+
level1Items.push(child);
|
|
58
|
+
items.push(child);
|
|
59
|
+
break;
|
|
66
60
|
}
|
|
67
|
-
case NavigationHeader:
|
|
68
|
-
case NavigationFooter:
|
|
69
|
-
// already handled in headerComponent and footerComponent
|
|
70
|
-
return null;
|
|
71
61
|
default:
|
|
72
62
|
console.warn('[Mezzanine][Navigation]: Navigation only accepts NavigationOption, NavigationOptionCategory, NavigationHeader or NavigationFooter as children.');
|
|
73
|
-
return null;
|
|
74
63
|
}
|
|
75
64
|
}
|
|
76
|
-
return null;
|
|
77
65
|
});
|
|
78
|
-
return
|
|
79
|
-
}, []);
|
|
66
|
+
return { headerComponent, footerComponent, items, level1Items };
|
|
67
|
+
}, [flattenedChildren]);
|
|
68
|
+
const { contentRef, visibleCount } = useVisibleItems(items, collapsed);
|
|
69
|
+
const { collapsedItems, collapsedMenuItems } = useMemo(() => {
|
|
70
|
+
return {
|
|
71
|
+
collapsedItems: visibleCount !== null
|
|
72
|
+
? level1Items.slice(0, visibleCount)
|
|
73
|
+
: level1Items,
|
|
74
|
+
collapsedMenuItems: visibleCount !== null ? level1Items.slice(visibleCount) : [],
|
|
75
|
+
};
|
|
76
|
+
}, [level1Items, visibleCount]);
|
|
77
|
+
const [filterText, setFilterText] = useState('');
|
|
80
78
|
return (jsx("nav", { ...rest, ref: ref, className: cx(navigationClasses.host, collapsed ? navigationClasses.collapsed : navigationClasses.expand, className), children: jsxs(NavigationActivatedContext.Provider, { value: {
|
|
81
79
|
activatedPath: activatedPath || innerActivatedPath,
|
|
82
|
-
setActivatedPath: combineSetActivatedPath,
|
|
83
|
-
currentPathname,
|
|
84
80
|
collapsed,
|
|
81
|
+
currentPathname,
|
|
82
|
+
filterText,
|
|
85
83
|
handleCollapseChange,
|
|
86
|
-
|
|
84
|
+
setActivatedPath: combineSetActivatedPath,
|
|
85
|
+
}, children: [headerComponent, jsx(NavigationOptionLevelContext.Provider, { value: navigationOptionLevelContextDefaultValues, children: jsxs("div", { ref: contentRef, className: navigationClasses.content, children: [filter && (jsx(Input, { size: "sub", variant: "search", className: cx(navigationClasses.searchInput), value: filterText, onChange: (e) => setFilterText(e.target.value) })), jsxs("ul", { children: [collapsed ? collapsedItems : items, collapsed &&
|
|
86
|
+
visibleCount !== null &&
|
|
87
|
+
visibleCount < level1Items.length && (jsx(NavigationOverflowMenu, { items: collapsedMenuItems }))] }, collapsed ? 'collapsed' : 'expand')] }) }), footerComponent] }) }));
|
|
87
88
|
});
|
|
88
89
|
|
|
89
90
|
export { Navigation as default };
|
|
@@ -9,6 +9,10 @@ export interface NavigationHeaderProps extends NativeElementPropsWithoutKeyAndRe
|
|
|
9
9
|
* The title text displayed in the header.
|
|
10
10
|
*/
|
|
11
11
|
title: string;
|
|
12
|
+
/**
|
|
13
|
+
* Callback function invoked when the brand area (logo and title) is clicked.
|
|
14
|
+
*/
|
|
15
|
+
onBrandClick?: () => void;
|
|
12
16
|
}
|
|
13
17
|
declare const NavigationHeader: import("react").ForwardRefExoticComponent<NavigationHeaderProps & import("react").RefAttributes<HTMLElement>>;
|
|
14
18
|
export default NavigationHeader;
|
|
@@ -7,9 +7,10 @@ import { NavigationActivatedContext } from './context.js';
|
|
|
7
7
|
import cx from 'clsx';
|
|
8
8
|
|
|
9
9
|
const NavigationHeader = forwardRef((props, ref) => {
|
|
10
|
-
const { children, className, title, ...rest } = props;
|
|
10
|
+
const { children, className, title, onBrandClick, ...rest } = props;
|
|
11
11
|
const { collapsed, handleCollapseChange } = use(NavigationActivatedContext);
|
|
12
|
-
|
|
12
|
+
const BrandComponent = onBrandClick ? 'button' : 'span';
|
|
13
|
+
return (jsxs("header", { ...rest, ref: ref, className: cx(navigationHeaderClasses.host, collapsed && navigationHeaderClasses.collapsed, className), children: [jsx(NavigationIconButton, { onClick: () => handleCollapseChange(!collapsed), icon: SiderIcon }), jsxs(BrandComponent, { type: "button", className: navigationHeaderClasses.content, onClick: onBrandClick, children: [children, jsx("span", { className: navigationHeaderClasses.title, children: title })] })] }));
|
|
13
14
|
});
|
|
14
15
|
|
|
15
16
|
export { NavigationHeader as default };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
2
|
import { IconDefinition } from '@mezzanine-ui/icons';
|
|
3
3
|
import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
|
|
4
|
-
|
|
4
|
+
import { BadgeProps } from '../Badge';
|
|
5
|
+
export type NavigationOptionChild = ReactElement<NavigationOptionProps> | ReactElement<BadgeProps> | false | null | undefined;
|
|
5
6
|
export type NavigationOptionChildren = NavigationOptionChild | NavigationOptionChild[];
|
|
6
7
|
export interface NavigationOptionProps extends Omit<NativeElementPropsWithoutKeyAndRef<'li'>, 'onClick' | 'onMouseEnter' | 'onMouseLeave'> {
|
|
7
8
|
/**
|
|
@@ -19,17 +20,21 @@ export interface NavigationOptionProps extends Omit<NativeElementPropsWithoutKey
|
|
|
19
20
|
/**
|
|
20
21
|
* Unique ID of the item.
|
|
21
22
|
*/
|
|
23
|
+
id?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Href of the item.
|
|
26
|
+
*/
|
|
22
27
|
href?: string;
|
|
23
28
|
/**
|
|
24
29
|
* Set display title for sub-menu item.
|
|
25
30
|
*/
|
|
26
|
-
title
|
|
31
|
+
title: string;
|
|
27
32
|
/**
|
|
28
33
|
* Open menu as default
|
|
29
34
|
* @default false
|
|
30
35
|
*/
|
|
31
36
|
defaultOpen?: boolean;
|
|
32
|
-
onTriggerClick?: (path: string[],
|
|
37
|
+
onTriggerClick?: (path: string[], currentKey: string, href?: string) => void;
|
|
33
38
|
}
|
|
34
39
|
declare const NavigationOption: import("react").ForwardRefExoticComponent<NavigationOptionProps & import("react").RefAttributes<HTMLLIElement>>;
|
|
35
40
|
export default NavigationOption;
|
|
@@ -1,54 +1,89 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { forwardRef, useState, use, useMemo, useEffect } from 'react';
|
|
3
|
+
import { forwardRef, useState, use, useId, useMemo, useEffect, Children, isValidElement } from 'react';
|
|
4
4
|
import { navigationOptionClasses } from '@mezzanine-ui/core/navigation';
|
|
5
5
|
import { ChevronUpIcon, ChevronDownIcon } from '@mezzanine-ui/icons';
|
|
6
6
|
import { NavigationOptionLevelContext, NavigationActivatedContext } from './context.js';
|
|
7
|
+
import { flattenChildren } from '../utils/flatten-children.js';
|
|
8
|
+
import Badge from '../Badge/Badge.js';
|
|
7
9
|
import Tooltip from '../Tooltip/Tooltip.js';
|
|
8
10
|
import Icon from '../Icon/Icon.js';
|
|
9
11
|
import Collapse from '../Transition/Collapse.js';
|
|
10
12
|
import cx from 'clsx';
|
|
11
13
|
|
|
12
14
|
const NavigationOption = forwardRef((props, ref) => {
|
|
13
|
-
const { active, children, className, defaultOpen = false, href, icon, onTriggerClick, title, ...rest } = props;
|
|
15
|
+
const { active, children, className, defaultOpen = false, href, icon, id, onTriggerClick, title, ...rest } = props;
|
|
14
16
|
const [open, setOpen] = useState(defaultOpen);
|
|
15
17
|
const GroupToggleIcon = open ? ChevronUpIcon : ChevronDownIcon;
|
|
16
18
|
const { level, path: parentPath } = use(NavigationOptionLevelContext);
|
|
17
|
-
const currentLevel = level + 1;
|
|
18
|
-
const
|
|
19
|
+
const currentLevel = level + 1; // start as 1
|
|
20
|
+
const uuid = useId();
|
|
21
|
+
const currentKey = id || title || href || uuid;
|
|
19
22
|
const currentPath = useMemo(() => [...parentPath, currentKey], [parentPath, currentKey]);
|
|
20
|
-
const { activatedPath,
|
|
23
|
+
const { activatedPath, collapsed, currentPathname, filterText, handleCollapseChange, setActivatedPath, } = use(NavigationActivatedContext);
|
|
21
24
|
useEffect(() => {
|
|
22
25
|
if (currentPathname === href) {
|
|
23
26
|
setActivatedPath(currentPath);
|
|
27
|
+
setOpen(true);
|
|
24
28
|
}
|
|
25
29
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
26
30
|
}, []);
|
|
27
31
|
const Component = href ? 'a' : 'div';
|
|
32
|
+
const flattenedChildren = useMemo(() => flattenChildren(children), [children]);
|
|
33
|
+
const { badge, items } = useMemo(() => {
|
|
34
|
+
let badgeComponent = null;
|
|
35
|
+
const items = [];
|
|
36
|
+
Children.forEach(flattenedChildren, (child) => {
|
|
37
|
+
if (child && isValidElement(child)) {
|
|
38
|
+
switch (child.type) {
|
|
39
|
+
case Badge: {
|
|
40
|
+
badgeComponent = child;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
case NavigationOption: {
|
|
44
|
+
items.push(child);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
default:
|
|
48
|
+
console.warn('[Mezzanine][NavigationOption]: NavigationOption only accepts NavigationOption or Badge as children.');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return { badge: badgeComponent, items };
|
|
53
|
+
}, [flattenedChildren]);
|
|
54
|
+
const [filter, setFilter] = useState(true);
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
var _a;
|
|
57
|
+
if (!filterText) {
|
|
58
|
+
setFilter(true);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
setFilter((_a = (title.includes(filterText) || (href === null || href === void 0 ? void 0 : href.includes(filterText)))) !== null && _a !== void 0 ? _a : false);
|
|
62
|
+
}, [currentPath, filterText, href, title]);
|
|
28
63
|
return (jsxs("li", { ...rest, ref: ref, className: cx(navigationOptionClasses.host, open && navigationOptionClasses.open, !children && navigationOptionClasses.basic, (active !== null && active !== void 0 ? active : (activatedPath === null || activatedPath === void 0 ? void 0 : activatedPath[currentLevel - 1]) === currentKey) &&
|
|
29
|
-
navigationOptionClasses.active, collapsed && navigationOptionClasses.collapsed, className), "data-id": currentKey, children: [jsx(Tooltip, { options: {
|
|
64
|
+
navigationOptionClasses.active, collapsed && navigationOptionClasses.collapsed, !collapsed && !filter && navigationOptionClasses.hidden, className), "data-id": currentKey, children: [jsx(Tooltip, { options: {
|
|
30
65
|
placement: 'right',
|
|
31
66
|
}, title: collapsed ? title : undefined, children: ({ onMouseEnter, onMouseLeave, ref: tooltipChildRef }) => (jsxs(Component, { className: cx(navigationOptionClasses.content, navigationOptionClasses.level(currentLevel)), onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, ref: tooltipChildRef, href: href, onClick: () => {
|
|
32
67
|
setOpen(!open);
|
|
33
|
-
onTriggerClick === null || onTriggerClick === void 0 ? void 0 : onTriggerClick(currentPath, href
|
|
68
|
+
onTriggerClick === null || onTriggerClick === void 0 ? void 0 : onTriggerClick(currentPath, currentKey, href);
|
|
34
69
|
if (collapsed) {
|
|
35
70
|
handleCollapseChange(false);
|
|
36
71
|
}
|
|
37
72
|
if (!children)
|
|
38
|
-
setActivatedPath(
|
|
73
|
+
setActivatedPath(currentPath);
|
|
39
74
|
}, onKeyDown: (e) => {
|
|
40
75
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
41
76
|
e.preventDefault();
|
|
42
77
|
setOpen(!open);
|
|
43
78
|
if (!children)
|
|
44
|
-
setActivatedPath(
|
|
79
|
+
setActivatedPath(currentPath);
|
|
45
80
|
}
|
|
46
|
-
}, role: "menuitem", tabIndex: 0, children: [icon && jsx(Icon, { className: navigationOptionClasses.icon, icon: icon }), jsx("span", { className: navigationOptionClasses.title, children: title }), children && (jsx(Icon, { className: navigationOptionClasses.toggleIcon, icon: GroupToggleIcon }))] })) }), children && !collapsed && (jsx(Collapse, { className: navigationOptionClasses.childrenWrapper, style: {
|
|
81
|
+
}, role: "menuitem", tabIndex: 0, children: [icon && jsx(Icon, { className: navigationOptionClasses.icon, icon: icon }), jsx("span", { className: navigationOptionClasses.title, children: title }), badge, children && (jsx(Icon, { className: navigationOptionClasses.toggleIcon, icon: GroupToggleIcon }))] })) }), children && !collapsed && (jsx(Collapse, { className: navigationOptionClasses.childrenWrapper, style: {
|
|
47
82
|
width: '100%',
|
|
48
83
|
}, in: !!open, children: jsx(NavigationOptionLevelContext.Provider, { value: {
|
|
49
84
|
level: currentLevel,
|
|
50
85
|
path: currentPath,
|
|
51
|
-
}, children: jsx("ul", { className: navigationOptionClasses.group, children:
|
|
86
|
+
}, children: jsx("ul", { className: navigationOptionClasses.group, children: items }) }) }))] }));
|
|
52
87
|
});
|
|
53
88
|
|
|
54
89
|
export { NavigationOption as default };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { FC, ReactElement } from 'react';
|
|
2
|
+
import { NavigationOptionProps } from './NavigationOption';
|
|
3
|
+
export interface NavigationOverflowMenuProps {
|
|
4
|
+
items: ReactElement<NavigationOptionProps>[];
|
|
5
|
+
}
|
|
6
|
+
export declare const NavigationOverflowMenu: FC<NavigationOverflowMenuProps>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { useState, useRef, useCallback, createElement, useMemo } from 'react';
|
|
2
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { navigationOverflowMenuClasses } from '@mezzanine-ui/core/navigation';
|
|
4
|
+
import NavigationIconButton from './NavigationIconButton.js';
|
|
5
|
+
import { DotHorizontalIcon } from '@mezzanine-ui/icons';
|
|
6
|
+
import NavigationOverflowMenuOption from './NavigationOverflowMenuOption.js';
|
|
7
|
+
import { TransitionGroup } from 'react-transition-group';
|
|
8
|
+
import { MOTION_EASING, MOTION_DURATION } from '@mezzanine-ui/system/motion';
|
|
9
|
+
import { NavigationOptionLevelContext } from './context.js';
|
|
10
|
+
import { useDocumentEvents } from '../hooks/useDocumentEvents.js';
|
|
11
|
+
import Popper from '../Popper/Popper.js';
|
|
12
|
+
import Translate from '../Transition/Translate.js';
|
|
13
|
+
|
|
14
|
+
const NavigationOverflowMenu = ({ items, }) => {
|
|
15
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
16
|
+
const targetRef = useRef(null);
|
|
17
|
+
const popperRef = useRef(null);
|
|
18
|
+
const [level1path, setLevel1path] = useState([]);
|
|
19
|
+
const [level2path, setLevel2path] = useState([]);
|
|
20
|
+
const [level2Items, setLevel2Items] = useState([]);
|
|
21
|
+
const [level3Items, setLevel3Items] = useState([]);
|
|
22
|
+
const renderMenuItem = useCallback((item, currentLevel) => createElement(NavigationOverflowMenuOption, {
|
|
23
|
+
...item.props,
|
|
24
|
+
onTriggerClick: (path, currentKey, href, subItems) => {
|
|
25
|
+
var _a, _b;
|
|
26
|
+
if (subItems && subItems.length > 0) {
|
|
27
|
+
if (currentLevel === 1) {
|
|
28
|
+
setLevel1path(path);
|
|
29
|
+
setLevel2Items(subItems);
|
|
30
|
+
setLevel3Items([]);
|
|
31
|
+
}
|
|
32
|
+
else if (currentLevel === 2) {
|
|
33
|
+
setLevel2path(path);
|
|
34
|
+
setLevel3Items(subItems);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
setMenuOpen(false);
|
|
39
|
+
}
|
|
40
|
+
(_b = (_a = item.props).onTriggerClick) === null || _b === void 0 ? void 0 : _b.call(_a, path, currentKey, href);
|
|
41
|
+
},
|
|
42
|
+
}), []);
|
|
43
|
+
const renderedItems = useMemo(() => items.map((item) => renderMenuItem(item, 1)), [items, renderMenuItem]);
|
|
44
|
+
const renderedItems2 = useMemo(() => level2Items.map((item) => renderMenuItem(item, 2)), [level2Items, renderMenuItem]);
|
|
45
|
+
const renderedItems3 = useMemo(() => level3Items.map((item) => renderMenuItem(item, 3)), [level3Items, renderMenuItem]);
|
|
46
|
+
const translateProps = useMemo(() => ({
|
|
47
|
+
duration: {
|
|
48
|
+
enter: MOTION_DURATION.moderate,
|
|
49
|
+
exit: MOTION_DURATION.moderate,
|
|
50
|
+
},
|
|
51
|
+
easing: {
|
|
52
|
+
enter: MOTION_EASING.standard,
|
|
53
|
+
exit: MOTION_EASING.standard,
|
|
54
|
+
},
|
|
55
|
+
}), []);
|
|
56
|
+
useDocumentEvents(() => {
|
|
57
|
+
if (!menuOpen) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const handleClickAway = (event) => {
|
|
61
|
+
const target = event.target;
|
|
62
|
+
const anchor = targetRef.current;
|
|
63
|
+
const popper = popperRef.current;
|
|
64
|
+
if (!target)
|
|
65
|
+
return;
|
|
66
|
+
if (anchor &&
|
|
67
|
+
popper &&
|
|
68
|
+
!anchor.contains(target) &&
|
|
69
|
+
!popper.contains(target)) {
|
|
70
|
+
setMenuOpen(false);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
click: handleClickAway,
|
|
75
|
+
touchend: handleClickAway,
|
|
76
|
+
};
|
|
77
|
+
}, [menuOpen]);
|
|
78
|
+
return (jsxs(Fragment, { children: [jsx(NavigationIconButton, { ref: targetRef, icon: DotHorizontalIcon, onClick: () => setMenuOpen(!menuOpen) }), jsx(Popper, { anchor: targetRef.current, disablePortal: true, open: menuOpen, options: {
|
|
79
|
+
placement: 'right-end',
|
|
80
|
+
}, ref: popperRef, children: jsx(TransitionGroup, { component: null, children: menuOpen && (createElement(Translate, { ...translateProps, from: 'bottom', key: "popper-list", in: true },
|
|
81
|
+
jsx("li", { className: navigationOverflowMenuClasses.host, children: jsxs("span", { className: navigationOverflowMenuClasses.content, "aria-haspopup": "true", "aria-expanded": menuOpen, children: [jsx("ul", { className: navigationOverflowMenuClasses.subMenu, children: renderedItems }), jsx(NavigationOptionLevelContext.Provider, { value: {
|
|
82
|
+
level: 1,
|
|
83
|
+
path: level1path,
|
|
84
|
+
}, children: level2Items.length > 0 && (jsx("ul", { className: navigationOverflowMenuClasses.subMenu, children: renderedItems2 })) }), jsx(NavigationOptionLevelContext.Provider, { value: {
|
|
85
|
+
level: 2,
|
|
86
|
+
path: level2path,
|
|
87
|
+
}, children: level3Items.length > 0 && (jsx("ul", { className: navigationOverflowMenuClasses.subMenu, children: renderedItems3 })) })] }) }))) }) })] }));
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export { NavigationOverflowMenu };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
import { NavigationOptionProps } from './NavigationOption';
|
|
3
|
+
export interface NavigationOverflowMenuOptionProps extends NavigationOptionProps {
|
|
4
|
+
onTriggerClick?: (path: string[], currentKey: string, href?: string, items?: ReactElement<NavigationOptionProps>[]) => void;
|
|
5
|
+
}
|
|
6
|
+
declare const NavigationOverflowMenuOption: import("react").ForwardRefExoticComponent<NavigationOverflowMenuOptionProps & import("react").RefAttributes<HTMLLIElement>>;
|
|
7
|
+
export default NavigationOverflowMenuOption;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
import { forwardRef, useState, use, useId, useMemo, useEffect, Children, isValidElement } from 'react';
|
|
4
|
+
import { navigationOverflowMenuOptionClasses } from '@mezzanine-ui/core/navigation';
|
|
5
|
+
import { ChevronRightIcon } from '@mezzanine-ui/icons';
|
|
6
|
+
import { NavigationOptionLevelContext, NavigationActivatedContext } from './context.js';
|
|
7
|
+
import { flattenChildren } from '../utils/flatten-children.js';
|
|
8
|
+
import NavigationOption from './NavigationOption.js';
|
|
9
|
+
import Badge from '../Badge/Badge.js';
|
|
10
|
+
import Icon from '../Icon/Icon.js';
|
|
11
|
+
import cx from 'clsx';
|
|
12
|
+
|
|
13
|
+
const NavigationOverflowMenuOption = forwardRef((props, ref) => {
|
|
14
|
+
const { active, children, className, defaultOpen = false, href, icon, id, onTriggerClick, title, ...rest } = props;
|
|
15
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
16
|
+
const { level, path: parentPath } = use(NavigationOptionLevelContext);
|
|
17
|
+
const currentLevel = level + 1; // start as 1
|
|
18
|
+
const uuid = useId();
|
|
19
|
+
const currentKey = id || title || href || uuid;
|
|
20
|
+
const currentPath = useMemo(() => [...parentPath, currentKey], [parentPath, currentKey]);
|
|
21
|
+
const { activatedPath, setActivatedPath, currentPathname } = use(NavigationActivatedContext);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (currentPathname === href) {
|
|
24
|
+
setActivatedPath(currentPath);
|
|
25
|
+
setOpen(true);
|
|
26
|
+
}
|
|
27
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28
|
+
}, []);
|
|
29
|
+
const Component = href ? 'a' : 'div';
|
|
30
|
+
const flattenedChildren = useMemo(() => flattenChildren(children), [children]);
|
|
31
|
+
const { badge, items } = useMemo(() => {
|
|
32
|
+
let badgeComponent = null;
|
|
33
|
+
const items = [];
|
|
34
|
+
Children.forEach(flattenedChildren, (child) => {
|
|
35
|
+
if (child && isValidElement(child)) {
|
|
36
|
+
switch (child.type) {
|
|
37
|
+
case Badge: {
|
|
38
|
+
badgeComponent = child;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case NavigationOption: {
|
|
42
|
+
items.push(child);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
default:
|
|
46
|
+
console.warn('[Mezzanine][NavigationOption]: NavigationOption only accepts NavigationOption or Badge as children.');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return { badge: badgeComponent, items };
|
|
51
|
+
}, [flattenedChildren]);
|
|
52
|
+
return (jsx("li", { ...rest, ref: ref, className: cx(navigationOverflowMenuOptionClasses.host, open && navigationOverflowMenuOptionClasses.open, !children && navigationOverflowMenuOptionClasses.basic, (active !== null && active !== void 0 ? active : (activatedPath === null || activatedPath === void 0 ? void 0 : activatedPath[currentLevel - 1]) === currentKey) &&
|
|
53
|
+
navigationOverflowMenuOptionClasses.active, className), "data-id": currentKey, children: jsxs(Component, { className: cx(navigationOverflowMenuOptionClasses.content), href: href, onClick: () => {
|
|
54
|
+
setOpen(!open);
|
|
55
|
+
onTriggerClick === null || onTriggerClick === void 0 ? void 0 : onTriggerClick(currentPath, currentKey, href, items);
|
|
56
|
+
if (!children)
|
|
57
|
+
setActivatedPath(currentPath);
|
|
58
|
+
}, onKeyDown: (e) => {
|
|
59
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
setOpen(!open);
|
|
62
|
+
if (!children)
|
|
63
|
+
setActivatedPath(currentPath);
|
|
64
|
+
}
|
|
65
|
+
}, role: "menuitem", tabIndex: 0, children: [icon && jsx(Icon, { className: navigationOverflowMenuOptionClasses.icon, icon: icon }), jsx("span", { className: navigationOverflowMenuOptionClasses.title, children: title }), badge, children && (jsx(Icon, { className: navigationOverflowMenuOptionClasses.toggleIcon, icon: ChevronRightIcon }))] }) }));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export { NavigationOverflowMenuOption as default };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
export interface NavigationUserMenuProps extends
|
|
2
|
+
import { DropdownProps } from '../Dropdown';
|
|
3
|
+
export interface NavigationUserMenuProps extends Omit<DropdownProps, 'children' | 'type'> {
|
|
4
4
|
children?: ReactNode;
|
|
5
|
+
className?: string;
|
|
5
6
|
imgSrc?: string;
|
|
7
|
+
onClick?: () => void;
|
|
6
8
|
}
|
|
7
9
|
declare const NavigationUserMenu: import("react").ForwardRefExoticComponent<NavigationUserMenuProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
8
10
|
export default NavigationUserMenu;
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { forwardRef, useState } from 'react';
|
|
3
3
|
import { navigationUserMenuClasses } from '@mezzanine-ui/core/navigation';
|
|
4
4
|
import { UserIcon, ChevronDownIcon } from '@mezzanine-ui/icons';
|
|
5
|
+
import Dropdown from '../Dropdown/Dropdown.js';
|
|
5
6
|
import Icon from '../Icon/Icon.js';
|
|
6
7
|
import cx from 'clsx';
|
|
7
8
|
|
|
8
9
|
const NavigationUserMenu = forwardRef((props, ref) => {
|
|
10
|
+
// shared props
|
|
9
11
|
const { children, className, imgSrc, onClick, ...rest } = props;
|
|
12
|
+
const { open: openProp, onClose, placement = 'top-end', onVisibilityChange, ...dropdownRest } = rest;
|
|
10
13
|
const [imgError, setImgError] = useState(false);
|
|
11
|
-
const [
|
|
12
|
-
|
|
14
|
+
const [_open, setOpen] = useState(false);
|
|
15
|
+
const open = openProp !== null && openProp !== void 0 ? openProp : _open;
|
|
16
|
+
return (jsx(Dropdown, { ...dropdownRest, open: open, placement: placement, onVisibilityChange: () => {
|
|
13
17
|
setOpen(!open);
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(!open);
|
|
19
|
+
onClick === null || onClick === void 0 ? void 0 : onClick();
|
|
20
|
+
}, onClose: () => {
|
|
21
|
+
setOpen(false);
|
|
22
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
23
|
+
}, children: jsxs("button", { type: "button", ref: ref, className: cx(navigationUserMenuClasses.host, open && navigationUserMenuClasses.open, className), children: [jsx("span", { className: navigationUserMenuClasses.avatar, children: imgError ? (jsx(Icon, { icon: UserIcon })) : (jsx("img", { alt: "User avatar", className: navigationUserMenuClasses.avatar, src: imgSrc, onError: () => setImgError(true) })) }), children && jsx("span", { className: navigationUserMenuClasses.userName, children: children }), jsx(Icon, { className: navigationUserMenuClasses.icon, icon: ChevronDownIcon })] }) }));
|
|
16
24
|
});
|
|
17
25
|
|
|
18
26
|
export { NavigationUserMenu as default };
|
package/Navigation/context.d.ts
CHANGED
|
@@ -8,8 +8,9 @@ export declare const NavigationOptionLevelContext: import("react").Context<{
|
|
|
8
8
|
}>;
|
|
9
9
|
export declare const NavigationActivatedContext: import("react").Context<{
|
|
10
10
|
activatedPath: string[];
|
|
11
|
-
setActivatedPath: (path: string[]) => void;
|
|
12
|
-
currentPathname: string | null;
|
|
13
11
|
collapsed: boolean;
|
|
12
|
+
currentPathname: string | null;
|
|
13
|
+
filterText: string;
|
|
14
14
|
handleCollapseChange: (newCollapsed: boolean) => void;
|
|
15
|
+
setActivatedPath: (path: string[]) => void;
|
|
15
16
|
}>;
|