@mezzanine-ui/react 1.0.0-beta.1 → 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/Badge/Badge.js +2 -2
- package/Breadcrumb/BreadcrumbItem.d.ts +1 -1
- 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 +30 -0
- package/Description/Description.js +13 -0
- package/Description/DescriptionContent.d.ts +41 -0
- package/Description/DescriptionContent.js +14 -0
- package/Description/DescriptionGroup.d.ts +13 -0
- package/Description/DescriptionGroup.js +12 -0
- package/Description/DescriptionTitle.d.ts +45 -0
- package/Description/DescriptionTitle.js +17 -0
- package/Description/index.d.ts +8 -0
- package/Description/index.js +4 -0
- package/Dropdown/Dropdown.d.ts +43 -3
- package/Dropdown/Dropdown.js +154 -35
- package/Dropdown/DropdownAction.d.ts +1 -1
- package/Dropdown/DropdownAction.js +1 -4
- package/Dropdown/DropdownItem.d.ts +21 -4
- package/Dropdown/DropdownItem.js +23 -10
- package/Dropdown/DropdownItemCard.d.ts +5 -5
- package/Dropdown/DropdownItemCard.js +11 -10
- package/Dropdown/DropdownStatus.d.ts +2 -2
- 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/FormControlContext.d.ts +2 -2
- package/Form/FormField.d.ts +56 -4
- package/Form/FormField.js +10 -6
- package/Form/FormHintText.d.ts +24 -1
- package/Form/FormHintText.js +4 -4
- package/Form/FormLabel.d.ts +6 -3
- package/Form/FormLabel.js +5 -3
- package/Input/Input.d.ts +29 -3
- package/Input/Input.js +22 -6
- package/Input/PasswordStrengthIndicator/PasswordStrengthIndicator.js +1 -1
- 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 +17 -3
- package/Navigation/Navigation.js +48 -33
- package/Navigation/NavigationFooter.js +4 -2
- package/Navigation/NavigationHeader.d.ts +11 -1
- package/Navigation/NavigationHeader.js +6 -3
- package/Navigation/NavigationOption.d.ts +3 -2
- package/Navigation/NavigationOption.js +45 -26
- package/Navigation/NavigationOptionCategory.js +20 -2
- package/Navigation/context.d.ts +2 -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/Table.d.ts +53 -15
- package/Table/Table.js +178 -82
- package/Table/TableContext.d.ts +18 -42
- package/Table/components/TableActionsCell.d.ts +26 -0
- package/Table/components/TableActionsCell.js +78 -0
- package/Table/components/TableBody.d.ts +2 -5
- package/Table/components/TableBody.js +16 -19
- package/Table/components/TableBulkActions.d.ts +15 -0
- package/Table/components/TableBulkActions.js +26 -0
- package/Table/components/TableCell.d.ts +2 -0
- package/Table/components/TableCell.js +42 -10
- package/Table/components/TableColGroup.js +10 -112
- package/Table/components/TableColumnTitleMenu.d.ts +6 -0
- package/Table/components/TableColumnTitleMenu.js +20 -0
- package/Table/components/TableDragHandleCell.d.ts +2 -0
- package/Table/components/TableDragHandleCell.js +8 -1
- package/Table/components/TableExpandCell.d.ts +2 -0
- package/Table/components/TableExpandCell.js +8 -1
- package/Table/components/TableExpandedRow.js +3 -2
- package/Table/components/TableHeader.d.ts +2 -4
- package/Table/components/TableHeader.js +11 -14
- package/Table/components/TableResizeHandle.js +3 -7
- package/Table/components/TableRow.js +54 -20
- package/Table/components/TableSelectionCell.d.ts +5 -0
- package/Table/components/TableSelectionCell.js +12 -1
- package/Table/components/index.d.ts +1 -0
- package/Table/components/index.js +1 -0
- package/Table/hooks/index.d.ts +1 -1
- package/Table/hooks/index.js +1 -1
- package/Table/hooks/useTableDataSource.d.ts +2 -2
- package/Table/hooks/useTableExpansion.js +0 -6
- package/Table/hooks/useTableFixedOffsets.d.ts +1 -1
- package/Table/hooks/useTableFixedOffsets.js +24 -26
- package/Table/hooks/useTableResizedColumns.d.ts +2 -0
- package/Table/hooks/useTableResizedColumns.js +22 -0
- package/Table/hooks/useTableScroll.d.ts +3 -1
- package/Table/hooks/useTableScroll.js +25 -19
- package/Table/hooks/useTableSelection.js +32 -8
- package/Table/hooks/useTableVirtualization.d.ts +1 -1
- package/Table/index.d.ts +4 -4
- package/Table/index.js +5 -3
- package/Table/utils/calculateColumnWidths.d.ts +28 -0
- package/Table/utils/calculateColumnWidths.js +80 -0
- package/Table/utils/index.d.ts +2 -0
- package/Table/utils/index.js +1 -0
- package/Table/utils/useTableRowSelection.d.ts +5 -5
- package/Table/utils/useTableRowSelection.js +14 -6
- 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 +36 -20
- package/index.js +26 -7
- package/package.json +4 -4
- package/utils/format-number-with-commas.d.ts +4 -0
- package/utils/format-number-with-commas.js +27 -0
- package/utils/parse-number-with-commas.d.ts +4 -0
- package/utils/parse-number-with-commas.js +22 -0
- 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/Table/hooks/useTableColumns.d.ts +0 -8
- package/Table/hooks/useTableColumns.js +0 -91
package/Input/Input.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { DropdownOption } from '@mezzanine-ui/core/dropdown';
|
|
2
|
+
import { ChangeEventHandler, Ref } from 'react';
|
|
3
|
+
import { PopperPlacement } from '../Popper';
|
|
3
4
|
import { TextFieldAffixProps, TextFieldProps } from '../TextField';
|
|
5
|
+
import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
|
|
4
6
|
import { ActionButtonProps } from './ActionButton';
|
|
5
|
-
import { SelectButtonProps } from './SelectButton';
|
|
6
7
|
import { PasswordStrengthIndicatorProps } from './PasswordStrengthIndicator';
|
|
8
|
+
import { SelectButtonProps } from './SelectButton';
|
|
7
9
|
/**
|
|
8
10
|
* Base props shared by all Input variants
|
|
9
11
|
*/
|
|
@@ -152,6 +154,30 @@ export type SelectInputProps = InputBaseProps & {
|
|
|
152
154
|
selectButton: SelectButtonProps & {
|
|
153
155
|
position: 'prefix' | 'suffix' | 'both';
|
|
154
156
|
};
|
|
157
|
+
/**
|
|
158
|
+
* The options of the dropdown.
|
|
159
|
+
*/
|
|
160
|
+
options?: DropdownOption[];
|
|
161
|
+
/**
|
|
162
|
+
* The selected value of the dropdown.
|
|
163
|
+
*/
|
|
164
|
+
selectedValue?: string;
|
|
165
|
+
/**
|
|
166
|
+
* The onChange event handler of the dropdown.
|
|
167
|
+
*/
|
|
168
|
+
onSelect?: (value: string) => void;
|
|
169
|
+
/**
|
|
170
|
+
* The width of the dropdown.
|
|
171
|
+
*/
|
|
172
|
+
dropdownWidth?: number | string;
|
|
173
|
+
/**
|
|
174
|
+
* The max height of the dropdown.
|
|
175
|
+
*/
|
|
176
|
+
dropdownMaxHeight?: number | string;
|
|
177
|
+
/**
|
|
178
|
+
* The placement of the dropdown.
|
|
179
|
+
*/
|
|
180
|
+
dropdownPlacement?: PopperPlacement;
|
|
155
181
|
};
|
|
156
182
|
/**
|
|
157
183
|
* 8. Password Input - Password input with visibility toggle
|
package/Input/Input.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import { forwardRef, useRef, useState, useCallback } from 'react';
|
|
4
3
|
import { inputClasses } from '@mezzanine-ui/core/input';
|
|
5
|
-
import { useComposeRefs } from '../hooks/useComposeRefs.js';
|
|
6
|
-
import { useInputWithClearControlValue } from '../Form/useInputWithClearControlValue.js';
|
|
7
4
|
import { EyeIcon, EyeInvisibleIcon, SearchIcon } from '@mezzanine-ui/icons';
|
|
5
|
+
import { forwardRef, useRef, useState, useCallback } from 'react';
|
|
6
|
+
import { useInputWithClearControlValue } from '../Form/useInputWithClearControlValue.js';
|
|
7
|
+
import { useComposeRefs } from '../hooks/useComposeRefs.js';
|
|
8
8
|
import Icon from '../Icon/Icon.js';
|
|
9
|
+
import Dropdown from '../Dropdown/Dropdown.js';
|
|
9
10
|
import SelectButton from './SelectButton/SelectButton.js';
|
|
10
11
|
import ActionButton from './ActionButton/ActionButton.js';
|
|
11
12
|
import SpinnerButton from './SpinnerButton/SpinnerButton.js';
|
|
@@ -158,16 +159,31 @@ const Input = forwardRef(function Input(props, ref) {
|
|
|
158
159
|
}
|
|
159
160
|
case 'select': {
|
|
160
161
|
const selectProps = props;
|
|
161
|
-
const { selectButton } = selectProps;
|
|
162
|
+
const { selectButton, options, dropdownWidth = 120, dropdownMaxHeight = 114 } = selectProps;
|
|
163
|
+
const defaultOptions = options || [];
|
|
164
|
+
const selectedOptions = defaultOptions.length > 0
|
|
165
|
+
? defaultOptions.map((option) => ({
|
|
166
|
+
...option,
|
|
167
|
+
...(option.id === selectProps.selectedValue
|
|
168
|
+
? { checkSite: 'suffix' }
|
|
169
|
+
: {}),
|
|
170
|
+
}))
|
|
171
|
+
: [];
|
|
162
172
|
if (selectButton.position === 'both' ||
|
|
163
173
|
selectButton.position === 'prefix') {
|
|
164
174
|
const { ...restSelectButtonProps } = selectButton;
|
|
165
|
-
prefixExternalButton = (jsx(
|
|
175
|
+
prefixExternalButton = (jsx(Dropdown, { options: selectedOptions, value: selectProps.selectedValue, customWidth: dropdownWidth, maxHeight: dropdownMaxHeight, placement: "bottom-start", onSelect: (option) => {
|
|
176
|
+
var _a;
|
|
177
|
+
(_a = selectProps.onSelect) === null || _a === void 0 ? void 0 : _a.call(selectProps, option.id);
|
|
178
|
+
}, children: jsx(SelectButton, { ...restSelectButtonProps, disabled: restSelectButtonProps.disabled || disabled, size: size }) }));
|
|
166
179
|
}
|
|
167
180
|
if (selectButton.position === 'both' ||
|
|
168
181
|
selectButton.position === 'suffix') {
|
|
169
182
|
const { ...restSelectButtonProps } = selectButton;
|
|
170
|
-
suffixExternalButton = (jsx(
|
|
183
|
+
suffixExternalButton = (jsx(Dropdown, { options: selectedOptions, value: selectProps.selectedValue, customWidth: dropdownWidth, maxHeight: dropdownMaxHeight, placement: "bottom-start", onSelect: (option) => {
|
|
184
|
+
var _a;
|
|
185
|
+
(_a = selectProps.onSelect) === null || _a === void 0 ? void 0 : _a.call(selectProps, option.id);
|
|
186
|
+
}, children: jsx(SelectButton, { ...restSelectButtonProps, disabled: restSelectButtonProps.disabled || disabled, size: size }) }));
|
|
171
187
|
}
|
|
172
188
|
break;
|
|
173
189
|
}
|
|
@@ -12,7 +12,7 @@ const PasswordStrengthIndicator = forwardRef(function PasswordStrengthIndicator(
|
|
|
12
12
|
const { className, strength = 'weak', strengthText: strengthTextProp, strengthTextPrefix = '密碼強度:', hintTexts, ...rest } = props;
|
|
13
13
|
const strengthText = strengthTextProp ||
|
|
14
14
|
(strength === 'weak' ? '低' : strength === 'medium' ? '中' : '高');
|
|
15
|
-
return (jsxs("div", { ref: ref, className: cx(inputPasswordStrengthIndicatorClasses.host, className), ...rest, children: [jsx("div", { className: cx(inputPasswordStrengthIndicatorClasses.bar, inputPasswordStrengthIndicatorClasses.barState(strength)) }), jsxs("span", { className: inputPasswordStrengthIndicatorClasses.text, children: [strengthTextPrefix, jsx("mark", { children: strengthText })] }), hintTexts && hintTexts.length > 0 && (jsx("div", { className: inputPasswordStrengthIndicatorClasses.hintTextGroup, children: hintTexts.map((hintText, idx) => (jsx(FormHintText, {
|
|
15
|
+
return (jsxs("div", { ref: ref, className: cx(inputPasswordStrengthIndicatorClasses.host, className), ...rest, children: [jsx("div", { className: cx(inputPasswordStrengthIndicatorClasses.bar, inputPasswordStrengthIndicatorClasses.barState(strength)) }), jsxs("span", { className: inputPasswordStrengthIndicatorClasses.text, children: [strengthTextPrefix, jsx("mark", { children: strengthText })] }), hintTexts && hintTexts.length > 0 && (jsx("div", { className: inputPasswordStrengthIndicatorClasses.hintTextGroup, children: hintTexts.map((hintText, idx) => (jsx(FormHintText, { hintText: hintText.hint, severity: hintText.severity }, idx))) }))] }));
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
export { PasswordStrengthIndicator as default };
|
package/Modal/Modal.d.ts
CHANGED
|
@@ -1,34 +1,126 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ModalSize, ModalStatusType } from '@mezzanine-ui/core/modal';
|
|
2
|
+
import { ModalContainerProps } from './useModalContainer';
|
|
3
3
|
import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
|
|
4
|
-
|
|
4
|
+
import { ModalHeaderProps } from './ModalHeader';
|
|
5
|
+
import { ModalFooterProps } from './ModalFooter';
|
|
6
|
+
interface CommonModalProps extends Omit<ModalContainerProps, 'children'>, Pick<NativeElementPropsWithoutKeyAndRef<'div'>, 'children'>, Partial<Omit<ModalHeaderProps, 'children' | 'className' | 'title'>>, Partial<Omit<ModalFooterProps, 'children' | 'className' | 'confirmText'>> {
|
|
5
7
|
/**
|
|
6
8
|
* Whether to force full screen on any breakpoint.
|
|
7
9
|
* @default false
|
|
8
10
|
*/
|
|
9
11
|
fullScreen?: boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Controls whether or not to hide close button at top-end.
|
|
12
|
-
* @default false
|
|
13
|
-
*/
|
|
14
|
-
hideCloseIcon?: boolean;
|
|
15
12
|
/**
|
|
16
13
|
* Whether the modal is loading.
|
|
17
14
|
* Controls the loading prop of confirm button in modal actions.
|
|
18
15
|
*/
|
|
19
16
|
loading?: boolean;
|
|
20
17
|
/**
|
|
21
|
-
*
|
|
18
|
+
* Controls whether or not to display status icon before title.
|
|
22
19
|
* Notice that giving a status will only display the regular title.
|
|
23
20
|
* @default 'info'
|
|
24
21
|
*/
|
|
25
|
-
|
|
22
|
+
modalStatusType?: ModalStatusType;
|
|
23
|
+
/**
|
|
24
|
+
* Controls whether or not to show dismiss button at top-end.
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
showDismissButton?: boolean;
|
|
28
|
+
}
|
|
29
|
+
interface ExtendedSplitModalProps extends CommonModalProps {
|
|
30
|
+
/**
|
|
31
|
+
* Content for the left side in extendedSplit layout.
|
|
32
|
+
* Required when modalType is 'extendedSplit'.
|
|
33
|
+
*/
|
|
34
|
+
extendedSplitLeftSideContent: React.ReactNode;
|
|
35
|
+
/**
|
|
36
|
+
* Content for the right side in extendedSplit layout.
|
|
37
|
+
* Required when modalType is 'extendedSplit'.
|
|
38
|
+
*/
|
|
39
|
+
extendedSplitRightSideContent: React.ReactNode;
|
|
40
|
+
/**
|
|
41
|
+
* Controls the type/layout of the modal.
|
|
42
|
+
* - 'extendedSplit': Modal with split layout (footer inside left content)
|
|
43
|
+
*/
|
|
44
|
+
modalType: 'extendedSplit';
|
|
26
45
|
/**
|
|
27
46
|
* Controls the size of the modal.
|
|
28
|
-
*
|
|
47
|
+
* For extendedSplit type, only 'wide' is allowed.
|
|
48
|
+
* @default 'wide'
|
|
49
|
+
*/
|
|
50
|
+
size?: 'wide';
|
|
51
|
+
}
|
|
52
|
+
interface OtherModalProps extends CommonModalProps {
|
|
53
|
+
/**
|
|
54
|
+
* Content for the left side in extendedSplit layout.
|
|
55
|
+
* Cannot be provided when modalType is not 'extendedSplit'.
|
|
56
|
+
*/
|
|
57
|
+
extendedSplitLeftSideContent?: never;
|
|
58
|
+
/**
|
|
59
|
+
* Content for the right side in extendedSplit layout.
|
|
60
|
+
* Cannot be provided when modalType is not 'extendedSplit'.
|
|
61
|
+
*/
|
|
62
|
+
extendedSplitRightSideContent?: never;
|
|
63
|
+
/**
|
|
64
|
+
* Controls the type/layout of the modal.
|
|
65
|
+
* - 'standard': Default modal with body container
|
|
66
|
+
* - 'extended': Modal with left and right content areas
|
|
67
|
+
* - 'mediaPreview': Modal for media preview
|
|
68
|
+
* - 'verification': Modal for verification flows
|
|
69
|
+
* @default 'standard'
|
|
70
|
+
*/
|
|
71
|
+
modalType: 'extended' | 'standard' | 'mediaPreview' | 'verification';
|
|
72
|
+
/**
|
|
73
|
+
* Controls the size of the modal.
|
|
74
|
+
* @default 'regular'
|
|
29
75
|
*/
|
|
30
76
|
size?: ModalSize;
|
|
31
77
|
}
|
|
78
|
+
type BaseModalProps = ExtendedSplitModalProps | OtherModalProps;
|
|
79
|
+
type ModalHeaderPropsWithHeader = {
|
|
80
|
+
/**
|
|
81
|
+
* Whether to show modal header.
|
|
82
|
+
*/
|
|
83
|
+
showModalHeader: true;
|
|
84
|
+
/**
|
|
85
|
+
* The title of the modal header (required when showModalHeader is true).
|
|
86
|
+
*/
|
|
87
|
+
title: string;
|
|
88
|
+
};
|
|
89
|
+
type ModalHeaderPropsWithoutHeader = {
|
|
90
|
+
/**
|
|
91
|
+
* Whether to show modal header.
|
|
92
|
+
* @default false
|
|
93
|
+
*/
|
|
94
|
+
showModalHeader?: false;
|
|
95
|
+
/**
|
|
96
|
+
* The title of the modal header.
|
|
97
|
+
* Cannot be provided when showModalHeader is false.
|
|
98
|
+
*/
|
|
99
|
+
title?: never;
|
|
100
|
+
};
|
|
101
|
+
type ModalFooterPropsWithFooter = {
|
|
102
|
+
/**
|
|
103
|
+
* Whether to show modal footer.
|
|
104
|
+
*/
|
|
105
|
+
showModalFooter: true;
|
|
106
|
+
/**
|
|
107
|
+
* The confirm button text of the modal footer (required when showModalFooter is true).
|
|
108
|
+
*/
|
|
109
|
+
confirmText: string;
|
|
110
|
+
};
|
|
111
|
+
type ModalFooterPropsWithoutFooter = {
|
|
112
|
+
/**
|
|
113
|
+
* Whether to show modal footer.
|
|
114
|
+
* @default false
|
|
115
|
+
*/
|
|
116
|
+
showModalFooter?: false;
|
|
117
|
+
/**
|
|
118
|
+
* The confirm button text of the modal footer.
|
|
119
|
+
* Cannot be provided when showModalFooter is false.
|
|
120
|
+
*/
|
|
121
|
+
confirmText?: never;
|
|
122
|
+
};
|
|
123
|
+
export type ModalProps = BaseModalProps & ((ModalHeaderPropsWithHeader & ModalFooterPropsWithFooter) | (ModalHeaderPropsWithHeader & ModalFooterPropsWithoutFooter) | (ModalHeaderPropsWithoutHeader & ModalFooterPropsWithFooter) | (ModalHeaderPropsWithoutHeader & ModalFooterPropsWithoutFooter));
|
|
32
124
|
/**
|
|
33
125
|
* The react component for `mezzanine` modal.
|
|
34
126
|
*/
|
package/Modal/Modal.js
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { modalClasses } from '@mezzanine-ui/core/modal';
|
|
3
|
-
import { TimesIcon } from '@mezzanine-ui/icons';
|
|
4
3
|
import { forwardRef, useMemo } from 'react';
|
|
5
4
|
import { ModalControlContext } from './ModalControl.js';
|
|
6
5
|
import useModalContainer from './useModalContainer.js';
|
|
7
|
-
import
|
|
6
|
+
import ModalHeader from './ModalHeader.js';
|
|
7
|
+
import ModalFooter from './ModalFooter.js';
|
|
8
|
+
import ClearActions from '../ClearActions/ClearActions.js';
|
|
8
9
|
import cx from 'clsx';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* The react component for `mezzanine` modal.
|
|
12
13
|
*/
|
|
13
14
|
const Modal = forwardRef(function Modal(props, ref) {
|
|
14
|
-
const { children, className,
|
|
15
|
+
const { actionsButtonLayout, annotation, auxiliaryContentButtonProps, auxiliaryContentButtonText, auxiliaryContentChecked, auxiliaryContentLabel, auxiliaryContentOnChange, auxiliaryContentOnClick, auxiliaryContentType, cancelButtonProps, cancelText, children, className, confirmButtonProps, confirmText, container, disableCloseOnBackdropClick = false, disableCloseOnEscapeKeyDown = false, disablePortal = false, extendedSplitLeftSideContent, extendedSplitRightSideContent, fullScreen = false, loading = false, modalStatusType = 'info', modalType = 'standard', onBackdropClick, onCancel, onClose, onConfirm, open, passwordButtonProps, passwordButtonText, passwordChecked, passwordCheckedLabel, passwordCheckedOnChange, passwordOnClick, showCancelButton, showDismissButton = false, showModalFooter = false, showModalHeader, showStatusTypeIcon, size = 'regular', statusTypeIconLayout, supportingText, supportingTextAlign, title, titleAlign, ...rest } = props;
|
|
15
16
|
const modalControl = useMemo(() => ({
|
|
16
17
|
loading,
|
|
17
|
-
|
|
18
|
-
}), [loading,
|
|
18
|
+
modalStatusType: modalStatusType,
|
|
19
|
+
}), [loading, modalStatusType]);
|
|
19
20
|
const { Container: ModalContainer } = useModalContainer();
|
|
20
|
-
|
|
21
|
+
const renderModalFooter = () => (jsx(ModalFooter, { actionsButtonLayout: actionsButtonLayout, annotation: annotation, auxiliaryContentButtonProps: auxiliaryContentButtonProps, auxiliaryContentButtonText: auxiliaryContentButtonText, auxiliaryContentChecked: auxiliaryContentChecked, auxiliaryContentLabel: auxiliaryContentLabel, auxiliaryContentOnChange: auxiliaryContentOnChange, auxiliaryContentOnClick: auxiliaryContentOnClick, auxiliaryContentType: auxiliaryContentType, cancelButtonProps: cancelButtonProps, cancelText: cancelText, confirmButtonProps: confirmButtonProps, confirmText: confirmText, loading: loading, onCancel: onCancel, onConfirm: onConfirm, passwordButtonProps: passwordButtonProps, passwordButtonText: passwordButtonText, passwordChecked: passwordChecked, passwordCheckedLabel: passwordCheckedLabel, passwordCheckedOnChange: passwordCheckedOnChange, passwordOnClick: passwordOnClick, showCancelButton: showCancelButton }));
|
|
22
|
+
return (jsx(ModalControlContext.Provider, { value: modalControl, children: jsx(ModalContainer, { className: modalClasses.overlay, container: container, disableCloseOnBackdropClick: disableCloseOnBackdropClick, disableCloseOnEscapeKeyDown: disableCloseOnEscapeKeyDown, disablePortal: disablePortal, onBackdropClick: onBackdropClick, onClose: onClose, open: open, ref: ref, children: jsxs("div", { ...rest, className: cx(modalClasses.host, modalClasses.modalStatusType(modalStatusType), modalClasses.size(size), {
|
|
21
23
|
[modalClasses.fullScreen]: fullScreen,
|
|
22
|
-
[modalClasses.withCloseIcon]:
|
|
23
|
-
}, className), role: "dialog", children: [
|
|
24
|
+
[modalClasses.withCloseIcon]: showDismissButton,
|
|
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
|
+
modalType === 'verification' ||
|
|
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" }))] }) }) }));
|
|
24
29
|
});
|
|
25
30
|
|
|
26
31
|
export { Modal as default };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
|
|
2
|
+
export interface ModalBodyForVerificationProps extends Omit<NativeElementPropsWithoutKeyAndRef<'div'>, 'onChange'> {
|
|
3
|
+
/**
|
|
4
|
+
* Whether to auto focus the first input when mounted.
|
|
5
|
+
* @default true
|
|
6
|
+
*/
|
|
7
|
+
autoFocus?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Whether the inputs are disabled.
|
|
10
|
+
* @default false
|
|
11
|
+
*/
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Whether the inputs are in error state.
|
|
15
|
+
* @default false
|
|
16
|
+
*/
|
|
17
|
+
error?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Number of verification code digits.
|
|
20
|
+
* @default 4
|
|
21
|
+
*/
|
|
22
|
+
length?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Called when verification code changes.
|
|
25
|
+
*/
|
|
26
|
+
onChange?: (value: string) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Called when all digits are filled.
|
|
29
|
+
*/
|
|
30
|
+
onComplete?: (value: string) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Called when resend link is clicked.
|
|
33
|
+
*/
|
|
34
|
+
onResend?: () => void;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the inputs are readonly.
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
readOnly?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Prompt text before resend link.
|
|
42
|
+
* @default "收不到驗證碼?"
|
|
43
|
+
*/
|
|
44
|
+
resendPrompt?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Resend link text.
|
|
47
|
+
* @default "點此重新寄送"
|
|
48
|
+
*/
|
|
49
|
+
resendText?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Current verification code value.
|
|
52
|
+
*/
|
|
53
|
+
value?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The react component for verification code input in modal.
|
|
57
|
+
*/
|
|
58
|
+
declare const ModalBodyForVerification: import("react").ForwardRefExoticComponent<ModalBodyForVerificationProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
59
|
+
export default ModalBodyForVerification;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { forwardRef, useState, useRef, useEffect } from 'react';
|
|
4
|
+
import { modalClasses } from '@mezzanine-ui/core/modal';
|
|
5
|
+
import Typography from '../Typography/Typography.js';
|
|
6
|
+
import cx from 'clsx';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The react component for verification code input in modal.
|
|
10
|
+
*/
|
|
11
|
+
const ModalBodyForVerification = forwardRef(function ModalBodyForVerification(props, ref) {
|
|
12
|
+
const { autoFocus = true, className, disabled = false, error = false, length = 4, onChange, onComplete, onResend, readOnly = false, resendPrompt = '收不到驗證碼?', resendText = '點此重新寄送', value = '', ...rest } = props;
|
|
13
|
+
const [codes, setCodes] = useState(value
|
|
14
|
+
.split('')
|
|
15
|
+
.slice(0, length)
|
|
16
|
+
.concat(Array(length - value.length).fill('')));
|
|
17
|
+
const inputRefs = useRef([]);
|
|
18
|
+
// Auto focus first input when mounted
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
var _a;
|
|
21
|
+
if (autoFocus && !disabled && !readOnly) {
|
|
22
|
+
(_a = inputRefs.current[0]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
23
|
+
}
|
|
24
|
+
}, [autoFocus, disabled, readOnly]);
|
|
25
|
+
const handleChange = (index, newValue) => {
|
|
26
|
+
var _a;
|
|
27
|
+
if (disabled || readOnly)
|
|
28
|
+
return;
|
|
29
|
+
// Only allow single digit/letter
|
|
30
|
+
const sanitized = newValue.slice(-1);
|
|
31
|
+
const newCodes = [...codes];
|
|
32
|
+
newCodes[index] = sanitized;
|
|
33
|
+
setCodes(newCodes);
|
|
34
|
+
const fullValue = newCodes.join('');
|
|
35
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(fullValue);
|
|
36
|
+
// Auto focus next input
|
|
37
|
+
if (sanitized && index < length - 1) {
|
|
38
|
+
(_a = inputRefs.current[index + 1]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
39
|
+
}
|
|
40
|
+
// Call onComplete when all filled
|
|
41
|
+
if (fullValue.length === length) {
|
|
42
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete(fullValue);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const handleKeyDown = (index, e) => {
|
|
46
|
+
var _a, _b, _c;
|
|
47
|
+
// Handle backspace
|
|
48
|
+
if (e.key === 'Backspace') {
|
|
49
|
+
if (disabled || readOnly)
|
|
50
|
+
return;
|
|
51
|
+
if (!codes[index] && index > 0) {
|
|
52
|
+
// If current is empty, focus previous
|
|
53
|
+
(_a = inputRefs.current[index - 1]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Clear current
|
|
57
|
+
const newCodes = [...codes];
|
|
58
|
+
newCodes[index] = '';
|
|
59
|
+
setCodes(newCodes);
|
|
60
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newCodes.join(''));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Handle arrow keys
|
|
64
|
+
else if (e.key === 'ArrowLeft' && index > 0) {
|
|
65
|
+
(_b = inputRefs.current[index - 1]) === null || _b === void 0 ? void 0 : _b.focus();
|
|
66
|
+
}
|
|
67
|
+
else if (e.key === 'ArrowRight' && index < length - 1) {
|
|
68
|
+
(_c = inputRefs.current[index + 1]) === null || _c === void 0 ? void 0 : _c.focus();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const handlePaste = (e) => {
|
|
72
|
+
var _a;
|
|
73
|
+
if (disabled || readOnly)
|
|
74
|
+
return;
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
const pastedData = e.clipboardData.getData('text').slice(0, length);
|
|
77
|
+
const newCodes = pastedData
|
|
78
|
+
.split('')
|
|
79
|
+
.concat(Array(length - pastedData.length).fill(''));
|
|
80
|
+
setCodes(newCodes);
|
|
81
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(pastedData);
|
|
82
|
+
// Focus the next empty input or the last input
|
|
83
|
+
const nextEmptyIndex = Math.min(pastedData.length, length - 1);
|
|
84
|
+
(_a = inputRefs.current[nextEmptyIndex]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
85
|
+
if (pastedData.length === length) {
|
|
86
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete(pastedData);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const handleInputChange = (index, e) => {
|
|
90
|
+
handleChange(index, e.target.value);
|
|
91
|
+
};
|
|
92
|
+
return (jsxs("div", { ...rest, ref: ref, className: cx(modalClasses.modalBodyVerification, className), children: [jsx("div", { className: modalClasses.modalBodyVerificationInputs, children: Array.from({ length }).map((_, index) => (jsx("input", { ref: (el) => {
|
|
93
|
+
inputRefs.current[index] = el;
|
|
94
|
+
}, type: "text", inputMode: "numeric", maxLength: 1, value: codes[index] || '', onChange: (e) => handleInputChange(index, e), onKeyDown: (e) => handleKeyDown(index, e), onPaste: handlePaste, className: cx(modalClasses.modalBodyVerificationInput, {
|
|
95
|
+
[modalClasses.modalBodyVerificationInputError]: error,
|
|
96
|
+
}), autoComplete: "off", disabled: disabled, readOnly: readOnly }, index))) }), onResend && (jsxs("div", { className: modalClasses.modalBodyVerificationResend, children: [jsx(Typography, { variant: "caption", color: "text-neutral", children: resendPrompt }), jsx(Typography, { variant: "caption", color: "text-neutral", className: modalClasses.modalBodyVerificationResendLink, onClick: onResend, component: "span", style: { cursor: 'pointer', textDecoration: 'underline' }, children: resendText })] }))] }));
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
export { ModalBodyForVerification as default };
|
package/Modal/ModalControl.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ModalStatusType } from '@mezzanine-ui/core/modal';
|
|
2
2
|
export interface ModalControl {
|
|
3
3
|
loading: boolean;
|
|
4
|
-
|
|
4
|
+
modalStatusType: ModalStatusType;
|
|
5
5
|
}
|
|
6
6
|
export declare const ModalControlContext: import("react").Context<ModalControl>;
|
package/Modal/ModalControl.js
CHANGED
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 };
|