@mezzanine-ui/react 1.0.0-beta.2 → 1.0.0-beta.3
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 +194 -0
- package/AutoComplete/AutoComplete.js +419 -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/Button/Button.js +13 -11
- package/Button/index.d.ts +1 -1
- package/Button/typings.d.ts +27 -4
- package/Description/Description.d.ts +12 -22
- package/Description/Description.js +4 -24
- package/Dropdown/Dropdown.d.ts +29 -1
- package/Dropdown/Dropdown.js +95 -14
- package/Dropdown/DropdownAction.d.ts +1 -1
- package/Dropdown/DropdownAction.js +1 -4
- package/Dropdown/DropdownItem.d.ts +18 -1
- package/Dropdown/DropdownItem.js +23 -10
- package/Dropdown/DropdownItemCard.js +11 -10
- 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/Form/FormField.js +3 -1
- package/Input/Input.d.ts +29 -3
- package/Input/Input.js +22 -6
- 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 +4 -5
- package/Modal/index.js +1 -2
- package/Modal/useModalContainer.d.ts +12 -3
- package/Modal/useModalContainer.js +28 -6
- package/Navigation/CollapsedMenu.d.ts +6 -0
- package/Navigation/CollapsedMenu.js +16 -0
- package/Navigation/Navigation.d.ts +7 -2
- package/Navigation/Navigation.js +33 -33
- package/Navigation/NavigationHeader.d.ts +4 -0
- package/Navigation/NavigationHeader.js +3 -2
- package/Navigation/NavigationOption.d.ts +2 -1
- package/Navigation/NavigationOption.js +28 -3
- package/Navigation/NavigationOptionCategory.js +1 -0
- package/Navigation/useVisibleItems.d.ts +5 -0
- package/Navigation/useVisibleItems.js +54 -0
- package/NotificationCenter/NotificationCenter.d.ts +124 -0
- package/NotificationCenter/NotificationCenter.js +259 -0
- package/NotificationCenter/NotificationCenterDrawer.d.ts +89 -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.js +4 -12
- package/PageToolbar/PageToolbar.d.ts +2 -6
- package/PageToolbar/utils.js +4 -12
- package/Select/index.d.ts +0 -2
- package/Select/index.js +0 -1
- package/Slider/useSlider.js +1 -1
- package/Table/components/TableActionsCell.js +2 -2
- package/Table/components/TableBulkActions.js +1 -19
- package/Table/components/TableRow.js +2 -2
- package/Table/hooks/useTableFixedOffsets.js +6 -6
- 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/Upload/UploadPictureCard.js +1 -1
- package/index.d.ts +34 -20
- package/index.js +19 -8
- package/package.json +4 -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/Select/AutoComplete.d.ts +0 -107
- package/Select/AutoComplete.js +0 -114
package/Modal/ModalFooter.d.ts
CHANGED
|
@@ -1,5 +1,123 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
|
|
2
|
-
|
|
3
|
+
import { ButtonProps } from '../Button/Button';
|
|
4
|
+
export interface ModalFooterProps extends NativeElementPropsWithoutKeyAndRef<'div'> {
|
|
5
|
+
/**
|
|
6
|
+
* Layout of action buttons.
|
|
7
|
+
* - 'fixed': Buttons maintain fixed width
|
|
8
|
+
* - 'fill': Buttons expand to fill available space equally
|
|
9
|
+
* @default 'fixed'
|
|
10
|
+
*/
|
|
11
|
+
actionsButtonLayout?: 'fill' | 'fixed';
|
|
12
|
+
/**
|
|
13
|
+
* Text to display as annotation on the left side.
|
|
14
|
+
* Only used when auxiliaryContentType is 'annotation'.
|
|
15
|
+
*/
|
|
16
|
+
annotation?: ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Props for the auxiliary content button.
|
|
19
|
+
* Only used when auxiliaryContentType is 'button'.
|
|
20
|
+
*/
|
|
21
|
+
auxiliaryContentButtonProps?: ButtonProps;
|
|
22
|
+
/**
|
|
23
|
+
* Text for the auxiliary content button.
|
|
24
|
+
* Only used when auxiliaryContentType is 'button'.
|
|
25
|
+
*/
|
|
26
|
+
auxiliaryContentButtonText?: ReactNode;
|
|
27
|
+
/**
|
|
28
|
+
* Whether the auxiliary content control (checkbox/toggle) is checked.
|
|
29
|
+
* Only used when auxiliaryContentType is 'checkbox' or 'toggle'.
|
|
30
|
+
*/
|
|
31
|
+
auxiliaryContentChecked?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Label text for the auxiliary content control (checkbox/toggle).
|
|
34
|
+
* Only used when auxiliaryContentType is 'checkbox' or 'toggle'.
|
|
35
|
+
*/
|
|
36
|
+
auxiliaryContentLabel?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Change handler for auxiliary content control (checkbox/toggle).
|
|
39
|
+
* Only used when auxiliaryContentType is 'checkbox' or 'toggle'.
|
|
40
|
+
*/
|
|
41
|
+
auxiliaryContentOnChange?: (checked: boolean) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Click handler for the auxiliary content button.
|
|
44
|
+
* Only used when auxiliaryContentType is 'button'.
|
|
45
|
+
*/
|
|
46
|
+
auxiliaryContentOnClick?: ButtonProps['onClick'];
|
|
47
|
+
/**
|
|
48
|
+
* Type of auxiliary content to show on the left side of the footer.
|
|
49
|
+
* - 'annotation': Display text annotation
|
|
50
|
+
* - 'button': Display a button
|
|
51
|
+
* - 'checkbox': Display a checkbox control
|
|
52
|
+
* - 'toggle': Display a toggle control
|
|
53
|
+
* - 'password': Display password-specific controls (remember me + forgot password)
|
|
54
|
+
* @default undefined (no auxiliary content)
|
|
55
|
+
*/
|
|
56
|
+
auxiliaryContentType?: 'annotation' | 'button' | 'checkbox' | 'toggle' | 'password';
|
|
57
|
+
/**
|
|
58
|
+
* Additional props for the cancel button.
|
|
59
|
+
*/
|
|
60
|
+
cancelButtonProps?: ButtonProps;
|
|
61
|
+
/**
|
|
62
|
+
* Text content of the cancel button.
|
|
63
|
+
*/
|
|
64
|
+
cancelText?: ReactNode;
|
|
65
|
+
/**
|
|
66
|
+
* Additional props for the confirm button.
|
|
67
|
+
*/
|
|
68
|
+
confirmButtonProps?: ButtonProps;
|
|
69
|
+
/**
|
|
70
|
+
* Text content of the confirm button.
|
|
71
|
+
*/
|
|
72
|
+
confirmText?: ReactNode;
|
|
73
|
+
/**
|
|
74
|
+
* Whether confirm button is loading and cancel button is disabled.
|
|
75
|
+
*/
|
|
76
|
+
loading?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Click handler for the cancel button.
|
|
79
|
+
*/
|
|
80
|
+
onCancel?: ButtonProps['onClick'];
|
|
81
|
+
/**
|
|
82
|
+
* Click handler for the confirm button.
|
|
83
|
+
*/
|
|
84
|
+
onConfirm?: ButtonProps['onClick'];
|
|
85
|
+
/**
|
|
86
|
+
* Props for the password auxiliary button.
|
|
87
|
+
* Only used when auxiliaryContentType is 'password'.
|
|
88
|
+
*/
|
|
89
|
+
passwordButtonProps?: ButtonProps;
|
|
90
|
+
/**
|
|
91
|
+
* Text for the password auxiliary button (e.g., "Forgot password?").
|
|
92
|
+
* Only used when auxiliaryContentType is 'password'.
|
|
93
|
+
*/
|
|
94
|
+
passwordButtonText?: ReactNode;
|
|
95
|
+
/**
|
|
96
|
+
* Whether the password checkbox is checked (e.g., "Remember me").
|
|
97
|
+
* Only used when auxiliaryContentType is 'password'.
|
|
98
|
+
*/
|
|
99
|
+
passwordChecked?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Label for the password checkbox (e.g., "Remember me").
|
|
102
|
+
* Only used when auxiliaryContentType is 'password'.
|
|
103
|
+
*/
|
|
104
|
+
passwordCheckedLabel?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Change handler for the password checkbox.
|
|
107
|
+
* Only used when auxiliaryContentType is 'password'.
|
|
108
|
+
*/
|
|
109
|
+
passwordCheckedOnChange?: (checked: boolean) => void;
|
|
110
|
+
/**
|
|
111
|
+
* Click handler for the password auxiliary button.
|
|
112
|
+
* Only used when auxiliaryContentType is 'password'.
|
|
113
|
+
*/
|
|
114
|
+
passwordOnClick?: ButtonProps['onClick'];
|
|
115
|
+
/**
|
|
116
|
+
* Whether to show the cancel button.
|
|
117
|
+
* @default true
|
|
118
|
+
*/
|
|
119
|
+
showCancelButton?: boolean;
|
|
120
|
+
}
|
|
3
121
|
/**
|
|
4
122
|
* The react component for `mezzanine` modal footer.
|
|
5
123
|
*/
|
package/Modal/ModalFooter.js
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { forwardRef } from 'react';
|
|
3
3
|
import { modalClasses } from '@mezzanine-ui/core/modal';
|
|
4
|
+
import Button from '../Button/Button.js';
|
|
5
|
+
import ButtonGroup from '../Button/ButtonGroup.js';
|
|
6
|
+
import Checkbox from '../Checkbox/Checkbox.js';
|
|
7
|
+
import Toggle from '../Toggle/Toggle.js';
|
|
8
|
+
import Typography from '../Typography/Typography.js';
|
|
4
9
|
import cx from 'clsx';
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
12
|
* The react component for `mezzanine` modal footer.
|
|
8
13
|
*/
|
|
9
14
|
const ModalFooter = forwardRef(function ModalFooter(props, ref) {
|
|
10
|
-
const { children, className, ...rest } = props;
|
|
11
|
-
|
|
15
|
+
const { children, className, actionsButtonLayout = 'fixed', annotation, auxiliaryContentButtonProps, auxiliaryContentButtonText, auxiliaryContentChecked, auxiliaryContentLabel, auxiliaryContentOnChange, auxiliaryContentOnClick, auxiliaryContentType, cancelButtonProps, cancelText, confirmButtonProps, confirmText, loading, onCancel, onConfirm, passwordButtonProps, passwordButtonText, passwordChecked, passwordCheckedLabel, passwordCheckedOnChange, passwordOnClick, showCancelButton = true, ...rest } = props;
|
|
16
|
+
const { disabled: cancelButtonDisabled = loading } = cancelButtonProps || {};
|
|
17
|
+
const isActionsButtonFillLayout = actionsButtonLayout === 'fill' && !auxiliaryContentType;
|
|
18
|
+
return (jsxs("div", { ...rest, ref: ref, className: cx(modalClasses.modalFooter, {
|
|
19
|
+
[modalClasses.modalFooter + '--password-mode']: auxiliaryContentType === 'password',
|
|
20
|
+
[modalClasses.modalFooter + '--with-auxiliary-content']: !!auxiliaryContentType && auxiliaryContentType !== 'password',
|
|
21
|
+
}, className), children: [auxiliaryContentType === 'password' && (jsxs("div", { className: modalClasses.modalFooterPasswordContainer, children: [jsx(Checkbox, { checked: passwordChecked, label: passwordCheckedLabel, onChange: (e) => passwordCheckedOnChange === null || passwordCheckedOnChange === void 0 ? void 0 : passwordCheckedOnChange(e.target.checked) }), jsx(Button, { variant: "base-text-link", ...passwordButtonProps, onClick: passwordOnClick, children: passwordButtonText })] })), auxiliaryContentType && auxiliaryContentType !== 'password' && (jsxs("div", { className: modalClasses.modalFooterAuxiliaryContentContainer, children: [auxiliaryContentType === 'annotation' && (jsx(Typography, { variant: "caption", color: "text-neutral", children: annotation })), auxiliaryContentType === 'button' && (jsx(Button, { variant: "base-text-link", ...auxiliaryContentButtonProps, onClick: auxiliaryContentOnClick, children: auxiliaryContentButtonText })), auxiliaryContentType === 'checkbox' && (jsx(Checkbox, { checked: auxiliaryContentChecked, label: auxiliaryContentLabel, onChange: (e) => auxiliaryContentOnChange === null || auxiliaryContentOnChange === void 0 ? void 0 : auxiliaryContentOnChange(e.target.checked) })), auxiliaryContentType === 'toggle' && (jsx(Toggle, { checked: auxiliaryContentChecked, label: auxiliaryContentLabel, onChange: (e) => auxiliaryContentOnChange === null || auxiliaryContentOnChange === void 0 ? void 0 : auxiliaryContentOnChange(e.target.checked) }))] })), jsxs(ButtonGroup, { className: cx(modalClasses.modalFooterActionsButtonContainer, {
|
|
22
|
+
[modalClasses.modalFooterActionsButtonContainer + '--fill-layout']: isActionsButtonFillLayout,
|
|
23
|
+
}), children: [showCancelButton && (jsx(Button, { variant: "base-secondary", ...cancelButtonProps, disabled: cancelButtonDisabled, onClick: onCancel, className: modalClasses.modalFooterActionsButton, children: cancelText })), jsx(Button, { variant: "base-primary", ...confirmButtonProps, loading: loading, onClick: onConfirm, className: modalClasses.modalFooterActionsButton, children: confirmText })] }), children] }));
|
|
12
24
|
});
|
|
13
25
|
|
|
14
26
|
export { ModalFooter as default };
|
package/Modal/ModalHeader.d.ts
CHANGED
|
@@ -1,19 +1,38 @@
|
|
|
1
1
|
import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
|
|
2
2
|
export interface ModalHeaderProps extends NativeElementPropsWithoutKeyAndRef<'div'> {
|
|
3
3
|
/**
|
|
4
|
-
* Whether to show
|
|
4
|
+
* Whether to show status type icon.
|
|
5
5
|
* @default false
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
showStatusTypeIcon?: boolean;
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* Layout of the status type icon relative to title.
|
|
10
|
+
* - 'vertical': Icon above title
|
|
11
|
+
* - 'horizontal': Icon to the left of title
|
|
12
|
+
* @default 'vertical'
|
|
13
|
+
*/
|
|
14
|
+
statusTypeIconLayout?: 'vertical' | 'horizontal';
|
|
15
|
+
/**
|
|
16
|
+
* Supporting text displayed below the title.
|
|
17
|
+
*/
|
|
18
|
+
supportingText?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Alignment of the supporting text.
|
|
21
|
+
* @default 'left'
|
|
22
|
+
*/
|
|
23
|
+
supportingTextAlign?: 'left' | 'center';
|
|
24
|
+
/**
|
|
25
|
+
* The title text of the modal header.
|
|
26
|
+
*/
|
|
27
|
+
title: string;
|
|
28
|
+
/**
|
|
29
|
+
* Alignment of the title.
|
|
30
|
+
* @default 'left'
|
|
12
31
|
*/
|
|
13
|
-
|
|
32
|
+
titleAlign?: 'left' | 'center';
|
|
14
33
|
}
|
|
15
34
|
/**
|
|
16
|
-
* The
|
|
35
|
+
* The React component for `mezzanine` modal header.
|
|
17
36
|
*/
|
|
18
37
|
declare const ModalHeader: import("react").ForwardRefExoticComponent<ModalHeaderProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
19
38
|
export default ModalHeader;
|
package/Modal/ModalHeader.js
CHANGED
|
@@ -1,20 +1,46 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { forwardRef, useContext } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { modalStatusTypeIcons, modalClasses } from '@mezzanine-ui/core/modal';
|
|
5
5
|
import { ModalControlContext } from './ModalControl.js';
|
|
6
|
+
import Typography from '../Typography/Typography.js';
|
|
6
7
|
import Icon from '../Icon/Icon.js';
|
|
7
8
|
import cx from 'clsx';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
|
-
* The
|
|
11
|
+
* The React component for `mezzanine` modal header.
|
|
11
12
|
*/
|
|
12
13
|
const ModalHeader = forwardRef(function ModalHeader(props, ref) {
|
|
13
|
-
const {
|
|
14
|
-
const {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const { className, showStatusTypeIcon = false, statusTypeIconLayout = 'vertical', supportingText, supportingTextAlign = 'left', title, titleAlign = 'left', ...rest } = props;
|
|
15
|
+
const { modalStatusType } = useContext(ModalControlContext);
|
|
16
|
+
const iconColor = (type) => {
|
|
17
|
+
switch (type) {
|
|
18
|
+
case 'success':
|
|
19
|
+
return 'success-strong';
|
|
20
|
+
case 'warning':
|
|
21
|
+
return 'warning';
|
|
22
|
+
case 'error':
|
|
23
|
+
return 'error-solid';
|
|
24
|
+
case 'info':
|
|
25
|
+
return 'info-strong';
|
|
26
|
+
case 'email':
|
|
27
|
+
return 'info-strong';
|
|
28
|
+
case 'delete':
|
|
29
|
+
return 'error-solid';
|
|
30
|
+
default:
|
|
31
|
+
return 'neutral';
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
return (jsxs("div", { ...rest, ref: ref, className: cx(modalClasses.modalHeader, {
|
|
35
|
+
[modalClasses.modalHeader + '--horizontal']: statusTypeIconLayout === 'horizontal',
|
|
36
|
+
[modalClasses.modalHeader + '--vertical']: statusTypeIconLayout === 'vertical',
|
|
37
|
+
[modalClasses.modalHeader + '--title-align-left']: titleAlign === 'left',
|
|
38
|
+
[modalClasses.modalHeader + '--title-align-center']: titleAlign === 'center',
|
|
39
|
+
[modalClasses.modalHeader + '--show-modal-status-type-icon']: showStatusTypeIcon,
|
|
40
|
+
}, className), children: [showStatusTypeIcon && (jsx("div", { className: cx(modalClasses.modalHeaderStatusTypeIcon), children: jsx(Icon, { icon: modalStatusTypeIcons[modalStatusType], color: iconColor(modalStatusType), size: 20 }) })), jsxs("div", { className: cx(modalClasses.modalHeaderTitleAndSupportingTextContainer), children: [jsx(Typography, { variant: "h3", color: "text-neutral-solid", className: cx(modalClasses.modalHeaderTitle), title: typeof title === 'string' ? title : undefined, children: title }), jsx(Typography, { variant: "body", color: "text-neutral-strong", className: cx(modalClasses.modalHeaderSupportingText, {
|
|
41
|
+
[modalClasses.modalHeaderSupportingText + '--align-left']: supportingTextAlign === 'left',
|
|
42
|
+
[modalClasses.modalHeaderSupportingText + '--align-center']: supportingTextAlign === 'center',
|
|
43
|
+
}), children: supportingText })] })] }));
|
|
18
44
|
});
|
|
19
45
|
|
|
20
46
|
export { ModalHeader as default };
|
package/Modal/index.d.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export type {
|
|
3
|
-
export { default as
|
|
4
|
-
export type { ModalBodyProps } from './ModalBody';
|
|
5
|
-
export { default as ModalBody } from './ModalBody';
|
|
1
|
+
export type { ModalStatusType, ModalSize } from '@mezzanine-ui/core/modal';
|
|
2
|
+
export type { ModalBodyForVerificationProps } from './ModalBodyForVerification';
|
|
3
|
+
export { default as ModalBodyForVerification } from './ModalBodyForVerification';
|
|
6
4
|
export type { ModalFooterProps } from './ModalFooter';
|
|
7
5
|
export { default as ModalFooter } from './ModalFooter';
|
|
8
6
|
export type { ModalHeaderProps } from './ModalHeader';
|
|
9
7
|
export { default as ModalHeader } from './ModalHeader';
|
|
10
8
|
export { default as useModalContainer } from './useModalContainer';
|
|
9
|
+
export type { ModalContainerProps } from './useModalContainer';
|
|
11
10
|
export type { ModalProps } from './Modal';
|
|
12
11
|
export { default } from './Modal';
|
package/Modal/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export { default as
|
|
2
|
-
export { default as ModalBody } from './ModalBody.js';
|
|
1
|
+
export { default as ModalBodyForVerification } from './ModalBodyForVerification.js';
|
|
3
2
|
export { default as ModalFooter } from './ModalFooter.js';
|
|
4
3
|
export { default as ModalHeader } from './ModalHeader.js';
|
|
5
4
|
export { default as useModalContainer } from './useModalContainer.js';
|
|
@@ -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 {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useRef } from 'react';
|
|
3
|
+
import { navigationClasses } from '@mezzanine-ui/core/navigation';
|
|
4
|
+
import NavigationIconButton from './NavigationIconButton.js';
|
|
5
|
+
import { DotHorizontalIcon } from '@mezzanine-ui/icons';
|
|
6
|
+
import Popper from '../Popper/Popper.js';
|
|
7
|
+
|
|
8
|
+
const CollapsedMenu = ({ items }) => {
|
|
9
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
10
|
+
const targetRef = useRef(null);
|
|
11
|
+
return (jsxs(Fragment, { children: [jsx(NavigationIconButton, { ref: targetRef, icon: DotHorizontalIcon, onClick: () => setMenuOpen(!menuOpen) }), jsx(Popper, { anchor: targetRef.current, open: menuOpen, options: {
|
|
12
|
+
placement: 'right-end',
|
|
13
|
+
}, children: jsx("div", { className: navigationClasses.collapsedMenu, children: jsx("ul", { children: items }) }) })] }));
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { CollapsedMenu };
|
|
@@ -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 { CollapsedMenu } from './CollapsedMenu.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,13 @@ const Navigation = forwardRef((props, ref) => {
|
|
|
27
29
|
}, [onOptionClick]);
|
|
28
30
|
const currentPathname = useCurrentPathname();
|
|
29
31
|
const flattenedChildren = useMemo(() => flattenChildren(children), [children]);
|
|
30
|
-
const
|
|
32
|
+
const [filterText, setFilterText] = useState('');
|
|
33
|
+
const { headerComponent, footerComponent, items, level1Items } = useMemo(() => {
|
|
31
34
|
let headerComponent = null;
|
|
32
35
|
let footerComponent = null;
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
const items = [];
|
|
37
|
+
const level1Items = [];
|
|
38
|
+
Children.forEach(flattenedChildren, (child, index) => {
|
|
35
39
|
if (child && isValidElement(child)) {
|
|
36
40
|
switch (child.type) {
|
|
37
41
|
case NavigationHeader: {
|
|
@@ -42,48 +46,44 @@ const Navigation = forwardRef((props, ref) => {
|
|
|
42
46
|
footerComponent = child;
|
|
43
47
|
break;
|
|
44
48
|
}
|
|
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
49
|
case NavigationOptionCategory:
|
|
50
|
+
level1Items.push(...(child.props.children
|
|
51
|
+
? flattenChildren(child.props.children, -1, [
|
|
52
|
+
child.props.title || 'NavigationOptionCategory:' + index,
|
|
53
|
+
])
|
|
54
|
+
: []));
|
|
55
|
+
items.push(child);
|
|
56
|
+
break;
|
|
64
57
|
case NavigationOption: {
|
|
65
|
-
|
|
58
|
+
level1Items.push(child);
|
|
59
|
+
items.push(child);
|
|
60
|
+
break;
|
|
66
61
|
}
|
|
67
|
-
case NavigationHeader:
|
|
68
|
-
case NavigationFooter:
|
|
69
|
-
// already handled in headerComponent and footerComponent
|
|
70
|
-
return null;
|
|
71
62
|
default:
|
|
72
63
|
console.warn('[Mezzanine][Navigation]: Navigation only accepts NavigationOption, NavigationOptionCategory, NavigationHeader or NavigationFooter as children.');
|
|
73
|
-
return null;
|
|
74
64
|
}
|
|
75
65
|
}
|
|
76
|
-
return null;
|
|
77
66
|
});
|
|
78
|
-
return
|
|
79
|
-
}, []);
|
|
67
|
+
return { headerComponent, footerComponent, items, level1Items };
|
|
68
|
+
}, [flattenedChildren]);
|
|
69
|
+
const { contentRef, visibleCount } = useVisibleItems(items, collapsed);
|
|
70
|
+
const { collapsedItems, collapsedMenuItems } = useMemo(() => {
|
|
71
|
+
return {
|
|
72
|
+
collapsedItems: visibleCount !== null
|
|
73
|
+
? level1Items.slice(0, visibleCount)
|
|
74
|
+
: level1Items,
|
|
75
|
+
collapsedMenuItems: visibleCount !== null ? level1Items.slice(visibleCount) : [],
|
|
76
|
+
};
|
|
77
|
+
}, [level1Items, visibleCount]);
|
|
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
80
|
setActivatedPath: combineSetActivatedPath,
|
|
83
81
|
currentPathname,
|
|
84
82
|
collapsed,
|
|
85
83
|
handleCollapseChange,
|
|
86
|
-
}, children: [headerComponent, jsx(NavigationOptionLevelContext.Provider, { value: navigationOptionLevelContextDefaultValues, children: jsxs("div", { className: navigationClasses.content, children: [
|
|
84
|
+
}, 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
|
+
visibleCount !== null &&
|
|
86
|
+
visibleCount < level1Items.length && (jsx(CollapsedMenu, { items: collapsedMenuItems }))] }, collapsed ? 'collapsed' : 'expand')] }) }), footerComponent] }) }));
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
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
|
/**
|
|
@@ -1,9 +1,11 @@
|
|
|
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, 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';
|
|
@@ -21,10 +23,33 @@ const NavigationOption = forwardRef((props, ref) => {
|
|
|
21
23
|
useEffect(() => {
|
|
22
24
|
if (currentPathname === href) {
|
|
23
25
|
setActivatedPath(currentPath);
|
|
26
|
+
setOpen(true);
|
|
24
27
|
}
|
|
25
28
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
26
29
|
}, []);
|
|
27
30
|
const Component = href ? 'a' : 'div';
|
|
31
|
+
const flattenedChildren = useMemo(() => flattenChildren(children), [children]);
|
|
32
|
+
const { badge, items } = useMemo(() => {
|
|
33
|
+
let badgeComponent = null;
|
|
34
|
+
const items = [];
|
|
35
|
+
Children.forEach(flattenedChildren, (child) => {
|
|
36
|
+
if (child && isValidElement(child)) {
|
|
37
|
+
switch (child.type) {
|
|
38
|
+
case Badge: {
|
|
39
|
+
badgeComponent = child;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
case NavigationOption: {
|
|
43
|
+
items.push(child);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
default:
|
|
47
|
+
console.warn('[Mezzanine][NavigationOption]: NavigationOption only accepts NavigationOption or Badge as children.');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return { badge: badgeComponent, items };
|
|
52
|
+
}, [flattenedChildren]);
|
|
28
53
|
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
54
|
navigationOptionClasses.active, collapsed && navigationOptionClasses.collapsed, className), "data-id": currentKey, children: [jsx(Tooltip, { options: {
|
|
30
55
|
placement: 'right',
|
|
@@ -43,12 +68,12 @@ const NavigationOption = forwardRef((props, ref) => {
|
|
|
43
68
|
if (!children)
|
|
44
69
|
setActivatedPath([...parentPath, currentKey]);
|
|
45
70
|
}
|
|
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: {
|
|
71
|
+
}, 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
72
|
width: '100%',
|
|
48
73
|
}, in: !!open, children: jsx(NavigationOptionLevelContext.Provider, { value: {
|
|
49
74
|
level: currentLevel,
|
|
50
75
|
path: currentPath,
|
|
51
|
-
}, children: jsx("ul", { className: navigationOptionClasses.group, children:
|
|
76
|
+
}, children: jsx("ul", { className: navigationOptionClasses.group, children: items }) }) }))] }));
|
|
52
77
|
});
|
|
53
78
|
|
|
54
79
|
export { NavigationOption as default };
|