@mezzanine-ui/react 1.0.0-beta.3 → 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.
Files changed (121) hide show
  1. package/AutoComplete/AutoComplete.d.ts +23 -0
  2. package/AutoComplete/AutoComplete.js +23 -9
  3. package/Breadcrumb/Breadcrumb.js +16 -21
  4. package/Breadcrumb/BreadcrumbDropdown.d.ts +11 -0
  5. package/Breadcrumb/BreadcrumbDropdown.js +22 -0
  6. package/Breadcrumb/BreadcrumbItem.d.ts +2 -3
  7. package/Breadcrumb/BreadcrumbItem.js +13 -31
  8. package/Breadcrumb/BreadcrumbOverflowMenu.d.ts +7 -0
  9. package/Breadcrumb/BreadcrumbOverflowMenu.js +77 -0
  10. package/Breadcrumb/BreadcrumbOverflowMenuDropdown.d.ts +11 -0
  11. package/Breadcrumb/BreadcrumbOverflowMenuDropdown.js +21 -0
  12. package/Breadcrumb/BreadcrumbOverflowMenuItem.d.ts +3 -0
  13. package/Breadcrumb/BreadcrumbOverflowMenuItem.js +27 -0
  14. package/Breadcrumb/typings.d.ts +21 -39
  15. package/Checkbox/index.d.ts +4 -5
  16. package/Checkbox/index.js +1 -5
  17. package/ContentHeader/ContentHeader.d.ts +160 -0
  18. package/ContentHeader/ContentHeader.js +54 -0
  19. package/ContentHeader/index.d.ts +2 -0
  20. package/ContentHeader/index.js +1 -0
  21. package/ContentHeader/utils.d.ts +23 -0
  22. package/ContentHeader/utils.js +215 -0
  23. package/Dropdown/Dropdown.d.ts +17 -0
  24. package/Dropdown/Dropdown.js +6 -2
  25. package/Dropdown/DropdownItem.d.ts +10 -0
  26. package/Dropdown/DropdownItem.js +37 -8
  27. package/Dropdown/DropdownItemCard.d.ts +2 -2
  28. package/Dropdown/DropdownItemCard.js +11 -8
  29. package/Empty/Empty.js +2 -1
  30. package/Empty/icons/EmptyMainNotificationIcon.d.ts +4 -0
  31. package/Empty/icons/EmptyMainNotificationIcon.js +9 -0
  32. package/Empty/typings.d.ts +2 -2
  33. package/FilterArea/Filter.d.ts +32 -0
  34. package/FilterArea/Filter.js +23 -0
  35. package/FilterArea/FilterArea.d.ts +58 -0
  36. package/FilterArea/FilterArea.js +31 -0
  37. package/FilterArea/FilterLine.d.ts +11 -0
  38. package/FilterArea/FilterLine.js +13 -0
  39. package/FilterArea/index.d.ts +6 -0
  40. package/FilterArea/index.js +3 -0
  41. package/Input/Input.d.ts +6 -4
  42. package/Input/Input.js +28 -10
  43. package/Input/index.d.ts +1 -1
  44. package/Modal/MediaPreviewModal.d.ts +54 -0
  45. package/Modal/MediaPreviewModal.js +158 -0
  46. package/Modal/Modal.js +1 -1
  47. package/Modal/index.d.ts +2 -0
  48. package/Modal/index.js +1 -0
  49. package/Navigation/Navigation.js +6 -5
  50. package/Navigation/NavigationOption.d.ts +6 -2
  51. package/Navigation/NavigationOption.js +19 -9
  52. package/Navigation/NavigationOverflowMenu.d.ts +6 -0
  53. package/Navigation/NavigationOverflowMenu.js +90 -0
  54. package/Navigation/NavigationOverflowMenuOption.d.ts +7 -0
  55. package/Navigation/NavigationOverflowMenuOption.js +68 -0
  56. package/Navigation/NavigationUserMenu.d.ts +4 -2
  57. package/Navigation/NavigationUserMenu.js +13 -5
  58. package/Navigation/context.d.ts +3 -2
  59. package/NotificationCenter/NotificationCenter.d.ts +1 -1
  60. package/NotificationCenter/NotificationCenter.js +34 -14
  61. package/NotificationCenter/NotificationCenterDrawer.d.ts +20 -0
  62. package/PageHeader/PageHeader.d.ts +32 -25
  63. package/PageHeader/PageHeader.js +49 -35
  64. package/ResultState/ResultState.d.ts +9 -0
  65. package/ResultState/ResultState.js +36 -4
  66. package/Scrollbar/Scrollbar.d.ts +9 -0
  67. package/Scrollbar/Scrollbar.js +78 -0
  68. package/Scrollbar/index.d.ts +2 -0
  69. package/Scrollbar/index.js +1 -0
  70. package/Scrollbar/typings.d.ts +47 -0
  71. package/Select/SelectTrigger.js +5 -4
  72. package/Select/typings.d.ts +6 -1
  73. package/Selection/Selection.js +1 -1
  74. package/Selection/SelectionGroup.d.ts +28 -0
  75. package/Table/Table.d.ts +2 -120
  76. package/Table/Table.js +148 -53
  77. package/Table/TableContext.d.ts +11 -12
  78. package/Table/components/TableActionsCell.js +12 -4
  79. package/Table/components/TableBody.js +2 -1
  80. package/Table/components/TableColGroup.d.ts +1 -4
  81. package/Table/components/TableColGroup.js +15 -16
  82. package/Table/components/TableCollectableCell.d.ts +17 -0
  83. package/Table/components/TableCollectableCell.js +54 -0
  84. package/Table/components/TableDragOrPinHandleCell.d.ts +20 -0
  85. package/Table/components/TableDragOrPinHandleCell.js +58 -0
  86. package/Table/components/TableExpandedRow.js +11 -2
  87. package/Table/components/TableHeader.js +12 -10
  88. package/Table/components/TableRow.js +38 -13
  89. package/Table/components/TableSelectionCell.js +1 -1
  90. package/Table/components/TableToggleableCell.d.ts +16 -0
  91. package/Table/components/TableToggleableCell.js +51 -0
  92. package/Table/components/index.d.ts +4 -1
  93. package/Table/components/index.js +3 -0
  94. package/Table/hooks/typings.d.ts +18 -4
  95. package/Table/hooks/useTableExpansion.d.ts +2 -2
  96. package/Table/hooks/useTableExpansion.js +5 -5
  97. package/Table/hooks/useTableFixedOffsets.d.ts +6 -2
  98. package/Table/hooks/useTableFixedOffsets.js +58 -24
  99. package/Table/hooks/useTableScroll.d.ts +9 -3
  100. package/Table/hooks/useTableScroll.js +34 -7
  101. package/Table/hooks/useTableVirtualization.d.ts +2 -1
  102. package/Table/hooks/useTableVirtualization.js +2 -8
  103. package/Table/index.d.ts +4 -3
  104. package/Table/index.js +3 -0
  105. package/Table/typings.d.ts +172 -0
  106. package/Transition/Slide.d.ts +9 -2
  107. package/Transition/Slide.js +7 -4
  108. package/Tree/TreeNode.js +1 -1
  109. package/index.d.ts +4 -2
  110. package/index.js +6 -3
  111. package/package.json +6 -4
  112. package/Navigation/CollapsedMenu.d.ts +0 -6
  113. package/Navigation/CollapsedMenu.js +0 -16
  114. package/PageToolbar/PageToolbar.d.ts +0 -110
  115. package/PageToolbar/PageToolbar.js +0 -23
  116. package/PageToolbar/index.d.ts +0 -2
  117. package/PageToolbar/index.js +0 -1
  118. package/PageToolbar/utils.d.ts +0 -23
  119. package/PageToolbar/utils.js +0 -157
  120. package/Table/components/TableDragHandleCell.d.ts +0 -11
  121. package/Table/components/TableDragHandleCell.js +0 -44
package/Modal/Modal.js CHANGED
@@ -25,7 +25,7 @@ const Modal = forwardRef(function Modal(props, ref) {
25
25
  }, className), role: "dialog", children: [showModalHeader && (jsx(ModalHeader, { showStatusTypeIcon: showStatusTypeIcon, statusTypeIconLayout: statusTypeIconLayout, supportingText: supportingText, supportingTextAlign: supportingTextAlign, title: title, titleAlign: titleAlign })), modalType === 'extendedSplit' && (jsxs("div", { className: modalClasses.modalBodyContainerExtendedSplit, children: [jsx("div", { className: modalClasses.modalBodyContainerExtendedSplitRight, children: extendedSplitRightSideContent }), jsxs("div", { className: modalClasses.modalBodyContainerExtendedSplitLeft, children: [jsx("div", { className: modalClasses.modalBodyContainerExtendedSplitLeftSideContent, children: extendedSplitLeftSideContent }), showModalFooter && renderModalFooter()] })] })), (modalType === 'standard' ||
26
26
  modalType === 'verification' ||
27
27
  modalType === 'extended' ||
28
- modalType === 'mediaPreview') && (jsxs(Fragment, { children: [jsx("div", { className: modalClasses.modalBodyContainer, children: children }), showModalFooter && renderModalFooter()] })), showDismissButton && (jsx(ClearActions, { onClick: onClose, className: modalClasses.closeIcon, variant: "base" }))] }) }) }));
28
+ modalType === 'mediaPreview') && (jsxs(Fragment, { children: [children && (jsx("div", { className: modalClasses.modalBodyContainer, children: children })), showModalFooter && renderModalFooter()] })), showDismissButton && (jsx(ClearActions, { onClick: onClose, className: modalClasses.closeIcon, variant: "base" }))] }) }) }));
29
29
  });
30
30
 
31
31
  export { Modal as default };
package/Modal/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export type { ModalFooterProps } from './ModalFooter';
5
5
  export { default as ModalFooter } from './ModalFooter';
6
6
  export type { ModalHeaderProps } from './ModalHeader';
7
7
  export { default as ModalHeader } from './ModalHeader';
8
+ export type { MediaPreviewModalProps } from './MediaPreviewModal';
9
+ export { default as MediaPreviewModal } from './MediaPreviewModal';
8
10
  export { default as useModalContainer } from './useModalContainer';
9
11
  export type { ModalContainerProps } from './useModalContainer';
10
12
  export type { ModalProps } from './Modal';
package/Modal/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { default as ModalBodyForVerification } from './ModalBodyForVerification.js';
2
2
  export { default as ModalFooter } from './ModalFooter.js';
3
3
  export { default as ModalHeader } from './ModalHeader.js';
4
+ export { default as MediaPreviewModal } from './MediaPreviewModal.js';
4
5
  export { default as useModalContainer } from './useModalContainer.js';
5
6
  export { default } from './Modal.js';
@@ -10,7 +10,7 @@ import NavigationOptionCategory from './NavigationOptionCategory.js';
10
10
  import { NavigationActivatedContext, NavigationOptionLevelContext, navigationOptionLevelContextDefaultValues } from './context.js';
11
11
  import { useCurrentPathname } from './useCurrentPathname.js';
12
12
  import { useVisibleItems } from './useVisibleItems.js';
13
- import { CollapsedMenu } from './CollapsedMenu.js';
13
+ import { NavigationOverflowMenu } from './NavigationOverflowMenu.js';
14
14
  import Input from '../Input/Input.js';
15
15
  import cx from 'clsx';
16
16
 
@@ -29,7 +29,6 @@ const Navigation = forwardRef((props, ref) => {
29
29
  }, [onOptionClick]);
30
30
  const currentPathname = useCurrentPathname();
31
31
  const flattenedChildren = useMemo(() => flattenChildren(children), [children]);
32
- const [filterText, setFilterText] = useState('');
33
32
  const { headerComponent, footerComponent, items, level1Items } = useMemo(() => {
34
33
  let headerComponent = null;
35
34
  let footerComponent = null;
@@ -75,15 +74,17 @@ const Navigation = forwardRef((props, ref) => {
75
74
  collapsedMenuItems: visibleCount !== null ? level1Items.slice(visibleCount) : [],
76
75
  };
77
76
  }, [level1Items, visibleCount]);
77
+ const [filterText, setFilterText] = useState('');
78
78
  return (jsx("nav", { ...rest, ref: ref, className: cx(navigationClasses.host, collapsed ? navigationClasses.collapsed : navigationClasses.expand, className), children: jsxs(NavigationActivatedContext.Provider, { value: {
79
79
  activatedPath: activatedPath || innerActivatedPath,
80
- setActivatedPath: combineSetActivatedPath,
81
- currentPathname,
82
80
  collapsed,
81
+ currentPathname,
82
+ filterText,
83
83
  handleCollapseChange,
84
+ setActivatedPath: combineSetActivatedPath,
84
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 &&
85
86
  visibleCount !== null &&
86
- visibleCount < level1Items.length && (jsx(CollapsedMenu, { items: collapsedMenuItems }))] }, collapsed ? 'collapsed' : 'expand')] }) }), footerComponent] }) }));
87
+ visibleCount < level1Items.length && (jsx(NavigationOverflowMenu, { items: collapsedMenuItems }))] }, collapsed ? 'collapsed' : 'expand')] }) }), footerComponent] }) }));
87
88
  });
88
89
 
89
90
  export { Navigation as default };
@@ -20,17 +20,21 @@ export interface NavigationOptionProps extends Omit<NativeElementPropsWithoutKey
20
20
  /**
21
21
  * Unique ID of the item.
22
22
  */
23
+ id?: string;
24
+ /**
25
+ * Href of the item.
26
+ */
23
27
  href?: string;
24
28
  /**
25
29
  * Set display title for sub-menu item.
26
30
  */
27
- title?: string;
31
+ title: string;
28
32
  /**
29
33
  * Open menu as default
30
34
  * @default false
31
35
  */
32
36
  defaultOpen?: boolean;
33
- onTriggerClick?: (path: string[], href: string) => void;
37
+ onTriggerClick?: (path: string[], currentKey: string, href?: string) => void;
34
38
  }
35
39
  declare const NavigationOption: import("react").ForwardRefExoticComponent<NavigationOptionProps & import("react").RefAttributes<HTMLLIElement>>;
36
40
  export default NavigationOption;
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { forwardRef, useState, use, useMemo, useEffect, Children, isValidElement } 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';
@@ -12,14 +12,15 @@ import Collapse from '../Transition/Collapse.js';
12
12
  import cx from 'clsx';
13
13
 
14
14
  const NavigationOption = forwardRef((props, ref) => {
15
- 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;
16
16
  const [open, setOpen] = useState(defaultOpen);
17
17
  const GroupToggleIcon = open ? ChevronUpIcon : ChevronDownIcon;
18
18
  const { level, path: parentPath } = use(NavigationOptionLevelContext);
19
- const currentLevel = level + 1;
20
- const currentKey = href || title || 'unknownId';
19
+ const currentLevel = level + 1; // start as 1
20
+ const uuid = useId();
21
+ const currentKey = id || title || href || uuid;
21
22
  const currentPath = useMemo(() => [...parentPath, currentKey], [parentPath, currentKey]);
22
- const { activatedPath, setActivatedPath, currentPathname, collapsed, handleCollapseChange, } = use(NavigationActivatedContext);
23
+ const { activatedPath, collapsed, currentPathname, filterText, handleCollapseChange, setActivatedPath, } = use(NavigationActivatedContext);
23
24
  useEffect(() => {
24
25
  if (currentPathname === href) {
25
26
  setActivatedPath(currentPath);
@@ -50,23 +51,32 @@ const NavigationOption = forwardRef((props, ref) => {
50
51
  });
51
52
  return { badge: badgeComponent, items };
52
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]);
53
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) &&
54
- 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: {
55
65
  placement: 'right',
56
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: () => {
57
67
  setOpen(!open);
58
- onTriggerClick === null || onTriggerClick === void 0 ? void 0 : onTriggerClick(currentPath, href || '');
68
+ onTriggerClick === null || onTriggerClick === void 0 ? void 0 : onTriggerClick(currentPath, currentKey, href);
59
69
  if (collapsed) {
60
70
  handleCollapseChange(false);
61
71
  }
62
72
  if (!children)
63
- setActivatedPath([...parentPath, currentKey]);
73
+ setActivatedPath(currentPath);
64
74
  }, onKeyDown: (e) => {
65
75
  if (e.key === 'Enter' || e.key === ' ') {
66
76
  e.preventDefault();
67
77
  setOpen(!open);
68
78
  if (!children)
69
- setActivatedPath([...parentPath, currentKey]);
79
+ setActivatedPath(currentPath);
70
80
  }
71
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: {
72
82
  width: '100%',
@@ -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 { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
3
- export interface NavigationUserMenuProps extends NativeElementPropsWithoutKeyAndRef<'button'> {
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 { jsxs, jsx } from 'react/jsx-runtime';
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 [open, setOpen] = useState(false);
12
- return (jsxs("button", { ...rest, className: cx(navigationUserMenuClasses.host, open && navigationUserMenuClasses.open, className), onClick: (e) => {
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
- onClick === null || onClick === void 0 ? void 0 : onClick(e);
15
- }, ref: ref, type: "button", 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 })] }));
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 };
@@ -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
  }>;
@@ -96,7 +96,7 @@ export interface NotificationData extends NotifierData, NotificationConfigProps
96
96
  * The time stamp of notification on the drawer list.
97
97
  * @default new Date().toLocaleTimeString()
98
98
  */
99
- timeStamp?: string;
99
+ timeStamp?: string | number;
100
100
  /**
101
101
  * The locale of the time stamp.
102
102
  * @default 'zh-TW'
@@ -87,21 +87,41 @@ const NotificationCenter = ((props) => {
87
87
  const [open, setOpen] = useState(true);
88
88
  const [timeStampAnchor, setTimeStampAnchor] = useState(null);
89
89
  const timeStampRef = useRef(null);
90
+ const isToday = useMemo(() => {
91
+ try {
92
+ const timestampDate = new Date(timeStamp);
93
+ // Check if the time stamp is a valid date
94
+ if (Number.isNaN(timestampDate.getTime())) {
95
+ return false;
96
+ }
97
+ const now = new Date();
98
+ const nowStartOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate());
99
+ const timestampStartOfDay = new Date(timestampDate.getFullYear(), timestampDate.getMonth(), timestampDate.getDate());
100
+ return timestampStartOfDay.getTime() === nowStartOfDay.getTime();
101
+ }
102
+ catch (_a) {
103
+ return false;
104
+ }
105
+ }, [timeStamp]);
90
106
  const formattedTimeStamp = useMemo(() => {
91
107
  try {
92
108
  const timestampDate = new Date(timeStamp);
109
+ const timeStampText = typeof timeStamp === 'string' ? timeStamp : String(timeStamp);
93
110
  // Check if the time stamp is a valid date
94
- if (isNaN(timestampDate.getTime())) {
95
- return timeStamp;
111
+ if (Number.isNaN(timestampDate.getTime())) {
112
+ return timeStampText;
96
113
  }
97
114
  const now = Date.now();
98
- const diffInMs = timestampDate.getTime() - now;
99
- const diffInSeconds = Math.round(diffInMs / 1000);
100
- const diffInDays = Math.round(diffInSeconds / 86400);
101
- if (Math.abs(diffInDays) <= 7) {
115
+ const nowDate = new Date(now);
116
+ const nowStartOfDay = new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate());
117
+ const timestampStartOfDay = new Date(timestampDate.getFullYear(), timestampDate.getMonth(), timestampDate.getDate());
118
+ const isToday = nowStartOfDay.getTime() === timestampStartOfDay.getTime();
119
+ // Only show relative time if the timestamp is today
120
+ if (isToday) {
121
+ const diffInMs = timestampDate.getTime() - now;
122
+ const diffInSeconds = Math.round(diffInMs / 1000);
102
123
  const rtf = new Intl.RelativeTimeFormat(timeStampLocale, { numeric: 'always' });
103
124
  const units = [
104
- { unit: 'day', seconds: 86400 },
105
125
  { unit: 'hour', seconds: 3600 },
106
126
  { unit: 'minute', seconds: 60 },
107
127
  ];
@@ -113,7 +133,7 @@ const NotificationCenter = ((props) => {
113
133
  }
114
134
  return 'now';
115
135
  }
116
- const hasTimeComponent = /:\d{2}/.test(timeStamp) || timeStamp.includes('T');
136
+ const hasTimeComponent = /:\d{2}/.test(timeStampText) || timeStampText.includes('T');
117
137
  if (hasTimeComponent) {
118
138
  const dateFormatter = new Intl.DateTimeFormat(timeStampLocale, {
119
139
  year: 'numeric',
@@ -135,7 +155,7 @@ const NotificationCenter = ((props) => {
135
155
  }
136
156
  }
137
157
  catch (_a) {
138
- return timeStamp;
158
+ return typeof timeStamp === 'string' ? timeStamp : String(timeStamp);
139
159
  }
140
160
  }, [timeStamp, timeStampLocale]);
141
161
  useEffect(() => {
@@ -186,7 +206,7 @@ const NotificationCenter = ((props) => {
186
206
  }
187
207
  }, [onBadgeSelectProp]);
188
208
  const handleNotificationMouseEnter = () => {
189
- if (type === 'drawer') {
209
+ if (type === 'drawer' && isToday) {
190
210
  setTimeout(() => {
191
211
  if (timeStampRef.current) {
192
212
  setTimeStampAnchor(timeStampRef.current);
@@ -195,7 +215,7 @@ const NotificationCenter = ((props) => {
195
215
  }
196
216
  };
197
217
  const handleNotificationMouseLeave = () => {
198
- if (type === 'drawer') {
218
+ if (type === 'drawer' && isToday) {
199
219
  setTimeStampAnchor(null);
200
220
  }
201
221
  };
@@ -208,7 +228,7 @@ const NotificationCenter = ((props) => {
208
228
  ? (jsx(Button, { onClick: onConfirm, size: "minor", ...confirmButtonProps, children: confirmButtonText }))
209
229
  : jsx(Fragment, {}), showCancelButton
210
230
  ? (jsx(Button, { onClick: onCancel || onClose, size: "minor", variant: "base-secondary", ...cancelButtonProps, children: cancelButtonText }))
211
- : jsx(Fragment, {})] })), type === 'drawer' && (jsxs(Fragment, { children: [jsx(Popper, { anchor: timeStampAnchor, open: Boolean(timeStampAnchor), arrow: {
231
+ : jsx(Fragment, {})] })), type === 'drawer' && (jsxs(Fragment, { children: [isToday && (jsx(Popper, { anchor: timeStampAnchor, open: Boolean(timeStampAnchor), arrow: {
212
232
  className: notificationClasses.timeStampPopperArrow,
213
233
  enabled: true,
214
234
  padding: 0,
@@ -220,11 +240,11 @@ const NotificationCenter = ((props) => {
220
240
  offset({ mainAxis: 8 }),
221
241
  flip(),
222
242
  ],
223
- }, children: jsx("div", { className: notificationClasses.timeStampPopper, children: jsx(Typography, { className: notificationClasses.timeStampText, children: timeStamp }) }) }), jsx(Typography, { ref: timeStampRef, className: notificationClasses.timeStamp, children: formattedTimeStamp })] }))] }), type === 'drawer'
243
+ }, children: jsx("div", { className: notificationClasses.timeStampPopper, children: jsx(Typography, { className: notificationClasses.timeStampText, children: timeStamp }) }) })), jsx(Typography, { ref: timeStampRef, className: notificationClasses.timeStamp, children: formattedTimeStamp })] }))] }), type === 'drawer'
224
244
  ? (jsx(Dropdown, { open: openDropdown, onClose: () => setOpenDropdown(false), onVisibilityChange: (open) => setOpenDropdown(open), options: options !== null && options !== void 0 ? options : [], onSelect: onSelect, placement: "bottom-end", zIndex: 'var(--mzn-z-index-popover)', children: jsxs(Button, { variant: "base-ghost", size: "minor", onClick: onClose, children: [showBadge && jsx(Badge, { variant: "dot-error" }), jsx(Icon, { icon: DotVerticalIcon, className: notificationClasses.closeIcon, size: 16, onClick: onBadgeClick })] }) }))
225
245
  : (jsx(Icon, { icon: CloseIcon, className: notificationClasses.closeIcon, size: 16, onClick: onClose }))] }));
226
246
  if (type === 'notification') {
227
- return (jsxs(Fragment, { children: [prependTips && jsx(Typography, { className: notificationClasses.prependTips, children: prependTips }), jsx(Slide, { in: open, appear: true, onExited: onExited, ...restTransitionProps, children: notificationContent }), appendTips && jsx(Typography, { className: notificationClasses.appendTips, children: appendTips })] }));
247
+ return (jsx(Slide, { in: open, appear: true, onExited: onExited, ...restTransitionProps, children: notificationContent }));
228
248
  }
229
249
  return (jsxs(Fragment, { children: [prependTips && jsx(Typography, { className: notificationClasses.prependTips, children: prependTips }), notificationContent, appendTips && jsx(Typography, { className: notificationClasses.appendTips, children: appendTips })] }));
230
250
  });
@@ -67,6 +67,26 @@ type NotificationCenterDrawerPropsBase = Pick<DrawerProps, 'open' | 'onClose'> &
67
67
  * The value of the radio group.
68
68
  */
69
69
  value?: string;
70
+ /**
71
+ * The label for the "earlier" time group.
72
+ * @default '更早'
73
+ */
74
+ earlierLabel?: string;
75
+ /**
76
+ * The label for the "past 7 days" time group.
77
+ * @default '過去七天'
78
+ */
79
+ past7DaysLabel?: string;
80
+ /**
81
+ * The label for the "today" time group.
82
+ * @default '今天'
83
+ */
84
+ todayLabel?: string;
85
+ /**
86
+ * The label for the "yesterday" time group.
87
+ * @default '昨天'
88
+ */
89
+ yesterdayLabel?: string;
70
90
  };
71
91
  export type NotificationCenterDrawerProps = (NotificationCenterDrawerPropsBase & {
72
92
  /**
@@ -1,40 +1,47 @@
1
- import { HTMLAttributes, ReactElement } from 'react';
1
+ import { ReactElement } from 'react';
2
2
  import { BreadcrumbProps } from '../Breadcrumb';
3
- import { ButtonProps } from '../Button';
4
- import { PageToolbarProps } from '../PageToolbar';
5
- import { TypographyProps } from '../Typography';
3
+ import { ContentHeaderProps } from '../ContentHeader';
6
4
  import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
7
- type PageHeaderChild = ReactElement<BreadcrumbProps> | ReactElement<PageToolbarProps> | ReactElement<ButtonProps> | ReactElement<HTMLAttributes<HTMLAnchorElement>> | null | undefined | false;
5
+ type PageHeaderChild = ReactElement<BreadcrumbProps> | ReactElement<ContentHeaderProps> | null | undefined | false;
8
6
  /**
9
7
  * Props for the PageHeader component.
10
8
  * Extends native HTML header element props.
11
9
  */
12
10
  export type PageHeaderProps = NativeElementPropsWithoutKeyAndRef<'header'> & {
13
- /** Optional back button properties */
14
- onBackClick?: () => void;
15
- /** Optional description text displayed below the title */
16
- description?: string;
17
- /** Main title text for the page header */
18
- title: string;
19
- /** HTML element type for the title (defaults to 'h2') */
20
- titleComponent?: TypographyProps['component'];
21
- /** Child components: Breadcrumb, PageToolbar, Button, or component with href prop */
11
+ /**
12
+ * Child components: Breadcrumb or ContentHeader
13
+ * */
22
14
  children?: PageHeaderChild | PageHeaderChild[];
23
15
  };
24
16
  /**
25
- * PageHeader component displays a page title with optional breadcrumb navigation,
26
- * description, back button, and action toolbar.
17
+ * PageHeader component
18
+ *
19
+ * Used to display the page header, typically containing a `<Breadcrumb />` and a `<ContentHeader />`.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * <PageHeader>
24
+ * <Breadcrumb
25
+ * links={[
26
+ * { id: '1', children: 'Home', href: '/' },
27
+ * { id: '2', children: 'Page Header' },
28
+ * ]}
29
+ * />
30
+ *
31
+ * <ContentHeader
32
+ * title="Page Title"
33
+ * description="This is the page description."
34
+ * >
35
+ * <Button variant="base-secondary">Secondary</Button>
36
+ * <Button>Primary</Button>
37
+ * </ContentHeader>
38
+ * </PageHeader>
39
+ * ```
27
40
  */
28
41
  declare const PageHeader: import("react").ForwardRefExoticComponent<NativeElementPropsWithoutKeyAndRef<"header"> & {
29
- /** Optional back button properties */
30
- onBackClick?: () => void;
31
- /** Optional description text displayed below the title */
32
- description?: string;
33
- /** Main title text for the page header */
34
- title: string;
35
- /** HTML element type for the title (defaults to 'h2') */
36
- titleComponent?: TypographyProps["component"];
37
- /** Child components: Breadcrumb, PageToolbar, Button, or component with href prop */
42
+ /**
43
+ * Child components: Breadcrumb or ContentHeader
44
+ * */
38
45
  children?: PageHeaderChild | PageHeaderChild[];
39
46
  } & import("react").RefAttributes<HTMLElement>>;
40
47
  export default PageHeader;