@mezzanine-ui/react 1.0.0-beta.4 → 1.0.0-beta.6
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/AutoComplete/AutoComplete.d.ts +5 -0
- package/AutoComplete/AutoComplete.js +19 -2
- package/Breadcrumb/BreadcrumbDropdown.js +1 -1
- package/Breadcrumb/BreadcrumbItem.js +1 -1
- package/Breadcrumb/BreadcrumbOverflowMenuItem.js +1 -1
- package/Calendar/Calendar.js +2 -6
- package/Calendar/CalendarCell.d.ts +22 -0
- package/Calendar/CalendarCell.js +6 -2
- package/Calendar/CalendarControls.js +1 -1
- package/Calendar/CalendarDayOfWeek.js +3 -2
- package/Calendar/CalendarDays.js +5 -1
- package/Calendar/CalendarHalfYears.js +13 -7
- package/Calendar/CalendarMonths.js +13 -6
- package/Calendar/CalendarQuarters.js +13 -7
- package/Calendar/CalendarWeeks.js +87 -34
- package/Calendar/CalendarYears.js +13 -12
- package/Calendar/useCalendarControlModifiers.d.ts +1 -1
- package/Calendar/useCalendarControlModifiers.js +12 -12
- package/Calendar/useCalendarControls.d.ts +4 -4
- package/Calendar/useCalendarControls.js +33 -19
- package/Calendar/useRangeCalendarControls.d.ts +8 -8
- package/Calendar/useRangeCalendarControls.js +42 -31
- package/DateRangePicker/useDateRangeCalendarControls.js +8 -2
- package/DateTimePicker/DateTimePicker.js +8 -4
- package/DateTimeRangePicker/DateTimeRangePicker.d.ts +34 -0
- package/DateTimeRangePicker/DateTimeRangePicker.js +118 -0
- package/DateTimeRangePicker/index.d.ts +2 -0
- package/DateTimeRangePicker/index.js +1 -0
- package/Drawer/Drawer.d.ts +132 -1
- package/Drawer/Drawer.js +47 -3
- package/Dropdown/Dropdown.d.ts +34 -3
- package/Dropdown/Dropdown.js +17 -29
- package/Dropdown/DropdownItem.d.ts +32 -0
- package/Dropdown/DropdownItem.js +112 -10
- package/Dropdown/DropdownItemCard.d.ts +5 -0
- package/Dropdown/DropdownItemCard.js +2 -2
- package/Form/FormField.d.ts +14 -2
- package/Form/FormField.js +3 -3
- package/Form/useSelectValueControl.d.ts +3 -4
- package/Form/useSelectValueControl.js +51 -39
- package/Input/Input.js +3 -19
- package/Input/SelectButton/SelectButton.d.ts +25 -4
- package/Input/SelectButton/SelectButton.js +21 -9
- package/Modal/MediaPreviewModal.d.ts +11 -0
- package/Modal/MediaPreviewModal.js +24 -7
- package/Modal/Modal.d.ts +1 -1
- package/Modal/Modal.js +1 -1
- package/Modal/useModalContainer.js +6 -2
- package/MultipleDatePicker/MultipleDatePicker.d.ts +62 -0
- package/MultipleDatePicker/MultipleDatePicker.js +176 -0
- package/MultipleDatePicker/MultipleDatePickerTrigger.d.ts +56 -0
- package/MultipleDatePicker/MultipleDatePickerTrigger.js +92 -0
- package/MultipleDatePicker/index.d.ts +6 -0
- package/MultipleDatePicker/index.js +3 -0
- package/MultipleDatePicker/useMultipleDatePickerValue.d.ts +55 -0
- package/MultipleDatePicker/useMultipleDatePickerValue.js +68 -0
- package/NotificationCenter/NotificationCenterDrawer.d.ts +10 -52
- package/NotificationCenter/NotificationCenterDrawer.js +128 -0
- package/NotificationCenter/index.d.ts +2 -0
- package/NotificationCenter/index.js +1 -0
- package/OverflowTooltip/index.d.ts +2 -2
- package/Picker/RangePickerTrigger.js +1 -1
- package/Popper/Popper.js +2 -1
- package/Scrollbar/Scrollbar.js +1 -0
- package/Section/Section.d.ts +32 -0
- package/Section/Section.js +62 -0
- package/Section/index.d.ts +2 -0
- package/Select/Select.d.ts +42 -18
- package/Select/Select.js +165 -51
- package/Select/TreeSelect.d.ts +10 -5
- package/Select/TreeSelect.js +12 -5
- package/Select/index.d.ts +8 -9
- package/Select/index.js +3 -3
- package/TimePanel/TimePanelColumn.js +16 -14
- package/TimeRangePicker/TimeRangePicker.d.ts +29 -0
- package/TimeRangePicker/TimeRangePicker.js +96 -0
- package/TimeRangePicker/index.d.ts +3 -0
- package/TimeRangePicker/index.js +2 -0
- package/TimeRangePicker/useTimeRangePickerValue.d.ts +30 -0
- package/TimeRangePicker/useTimeRangePickerValue.js +92 -0
- package/Transition/Rotate.js +2 -5
- package/Tree/TreeNode.js +2 -2
- package/index.d.ts +9 -6
- package/index.js +7 -6
- package/package.json +4 -4
- package/AppBar/AppBar.d.ts +0 -14
- package/AppBar/AppBar.js +0 -33
- package/AppBar/AppBarBrand.d.ts +0 -4
- package/AppBar/AppBarBrand.js +0 -11
- package/AppBar/AppBarMain.d.ts +0 -4
- package/AppBar/AppBarMain.js +0 -11
- package/AppBar/AppBarSupport.d.ts +0 -4
- package/AppBar/AppBarSupport.js +0 -11
- package/AppBar/index.d.ts +0 -8
- package/AppBar/index.js +0 -4
- package/Popconfirm/Popconfirm.d.ts +0 -16
- package/Popconfirm/Popconfirm.js +0 -15
- package/Popconfirm/index.d.ts +0 -2
- package/Popconfirm/index.js +0 -1
- package/Popover/Popover.d.ts +0 -23
- package/Popover/Popover.js +0 -35
- package/Popover/index.d.ts +0 -2
- package/Popover/index.js +0 -1
package/Select/Select.d.ts
CHANGED
|
@@ -1,33 +1,48 @@
|
|
|
1
|
+
import { DropdownOption, DropdownType } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
1
2
|
import { SelectInputSize } from '@mezzanine-ui/core/select';
|
|
3
|
+
import React, { ReactElement } from 'react';
|
|
2
4
|
import { FormElementFocusHandlers } from '../Form';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
import { SelectTriggerInputProps, SelectTriggerProps, SelectValue } from './typings';
|
|
6
|
+
export interface SelectBaseProps extends Omit<SelectTriggerProps, 'active' | 'inputProps' | 'mode' | 'onBlur' | 'onChange' | 'onClick' | 'onFocus' | 'onKeyDown' | 'onScroll' | 'type' | 'renderValue' | 'value'>, FormElementFocusHandlers {
|
|
7
|
+
/**
|
|
8
|
+
* The children of select (Option components).
|
|
9
|
+
* If `options` is provided, this will be ignored.
|
|
10
|
+
*/
|
|
11
|
+
children?: ReactElement | ReactElement[];
|
|
12
|
+
/**
|
|
13
|
+
* Direct options array for dropdown (supports tree structure).
|
|
14
|
+
* If provided, `children` will be ignored and `type` will be automatically set.
|
|
15
|
+
*/
|
|
16
|
+
options?: DropdownOption[];
|
|
17
|
+
/**
|
|
18
|
+
* The type of dropdown.
|
|
19
|
+
* @default 'default'
|
|
20
|
+
*/
|
|
21
|
+
type?: DropdownType;
|
|
16
22
|
/**
|
|
17
23
|
* The other native props for input element.
|
|
18
24
|
*/
|
|
19
25
|
inputProps?: Omit<SelectTriggerInputProps, 'onBlur' | 'onChange' | 'onFocus' | 'placeholder' | 'role' | 'value' | `aria-${'controls' | 'expanded' | 'owns'}`>;
|
|
26
|
+
/**
|
|
27
|
+
* The max height of the dropdown list.
|
|
28
|
+
*/
|
|
29
|
+
menuMaxHeight?: number | string;
|
|
20
30
|
/**
|
|
21
31
|
* Popup menu scroll listener
|
|
22
32
|
*/
|
|
23
|
-
|
|
33
|
+
onScroll?: (computed: {
|
|
24
34
|
scrollTop: number;
|
|
25
35
|
maxScrollTop: number;
|
|
26
|
-
}, target:
|
|
36
|
+
}, target: HTMLDivElement) => void;
|
|
27
37
|
/**
|
|
28
38
|
* select input placeholder
|
|
29
39
|
*/
|
|
30
40
|
placeholder?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the input is readonly.
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
readOnly?: boolean;
|
|
31
46
|
/**
|
|
32
47
|
* To customize rendering select input value
|
|
33
48
|
*/
|
|
@@ -41,6 +56,15 @@ export interface SelectBaseProps extends Omit<SelectTriggerProps, 'active' | 'in
|
|
|
41
56
|
* The size of input.
|
|
42
57
|
*/
|
|
43
58
|
size?: SelectInputSize;
|
|
59
|
+
/**
|
|
60
|
+
* The z-index of the dropdown.
|
|
61
|
+
*/
|
|
62
|
+
dropdownZIndex?: number | string;
|
|
63
|
+
/**
|
|
64
|
+
* Whether to enable portal for the dropdown.
|
|
65
|
+
* @default true
|
|
66
|
+
*/
|
|
67
|
+
globalPortal?: boolean;
|
|
44
68
|
}
|
|
45
69
|
export type SelectMultipleProps = SelectBaseProps & {
|
|
46
70
|
/**
|
|
@@ -54,7 +78,7 @@ export type SelectMultipleProps = SelectBaseProps & {
|
|
|
54
78
|
/**
|
|
55
79
|
* The change event handler of input element.
|
|
56
80
|
*/
|
|
57
|
-
onChange?(newOptions: SelectValue[]):
|
|
81
|
+
onChange?(newOptions: SelectValue[]): void;
|
|
58
82
|
/**
|
|
59
83
|
* To customize rendering select input value
|
|
60
84
|
*/
|
|
@@ -77,7 +101,7 @@ export type SelectSingleProps = SelectBaseProps & {
|
|
|
77
101
|
/**
|
|
78
102
|
* The change event handler of input element.
|
|
79
103
|
*/
|
|
80
|
-
onChange?(newOptions: SelectValue):
|
|
104
|
+
onChange?(newOptions: SelectValue | null): void;
|
|
81
105
|
/**
|
|
82
106
|
* To customize rendering select input value
|
|
83
107
|
*/
|
|
@@ -89,5 +113,5 @@ export type SelectSingleProps = SelectBaseProps & {
|
|
|
89
113
|
value?: SelectValue | null;
|
|
90
114
|
};
|
|
91
115
|
export type SelectProps = SelectMultipleProps | SelectSingleProps;
|
|
92
|
-
declare const Select:
|
|
116
|
+
declare const Select: React.ForwardRefExoticComponent<SelectProps & React.RefAttributes<HTMLDivElement>>;
|
|
93
117
|
export default Select;
|
package/Select/Select.js
CHANGED
|
@@ -1,41 +1,34 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx
|
|
3
|
-
import { forwardRef, useContext, useState, useRef, useCallback, useMemo } from 'react';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
3
|
import { selectClasses } from '@mezzanine-ui/core/select';
|
|
5
4
|
import isArray from 'lodash/isArray';
|
|
5
|
+
import React, { forwardRef, useContext, useState, useCallback, useRef, useMemo, Children } from 'react';
|
|
6
|
+
import { useSelectValueControl } from '../Form/useSelectValueControl.js';
|
|
6
7
|
import { useComposeRefs } from '../hooks/useComposeRefs.js';
|
|
8
|
+
import Option from './Option.js';
|
|
7
9
|
import { SelectControlContext } from './SelectControlContext.js';
|
|
8
|
-
import { useSelectValueControl } from '../Form/useSelectValueControl.js';
|
|
9
|
-
import { useClickAway } from '../hooks/useClickAway.js';
|
|
10
10
|
import SelectTrigger from './SelectTrigger.js';
|
|
11
11
|
import { FormControlContext } from '../Form/FormControlContext.js';
|
|
12
|
-
import
|
|
13
|
-
import Menu from '../Menu/Menu.js';
|
|
12
|
+
import Dropdown from '../Dropdown/Dropdown.js';
|
|
14
13
|
import cx from 'clsx';
|
|
15
14
|
|
|
16
|
-
const MENU_ID = 'mzn-select-menu-id';
|
|
17
15
|
const Select = forwardRef(function Select(props, ref) {
|
|
18
|
-
var _a, _b;
|
|
19
16
|
const { disabled: disabledFromFormControl, fullWidth: fullWidthFromFormControl, required: requiredFromFormControl, severity, } = useContext(FormControlContext) || {};
|
|
20
|
-
const { children, className, clearable = false, defaultValue, disabled = disabledFromFormControl || false,
|
|
17
|
+
const { children, className, clearable = false, defaultValue, disabled = disabledFromFormControl || false, error = severity === 'error' || false, fullWidth = fullWidthFromFormControl || false, inputProps, inputRef, menuMaxHeight, mode = 'single', onBlur, onChange: onChangeProp, onClear: onClearProp, onFocus, onScroll, options: optionsProp, placeholder = '', prefix, readOnly = false, renderValue, required = requiredFromFormControl || false, size, suffixActionIcon, type = 'default', value: valueProp, dropdownZIndex, globalPortal = true, } = props;
|
|
21
18
|
const [open, toggleOpen] = useState(false);
|
|
22
|
-
const onOpen = () => {
|
|
19
|
+
const onOpen = useCallback(() => {
|
|
20
|
+
// Prevent opening when readOnly is true
|
|
21
|
+
if (readOnly) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
23
24
|
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
24
25
|
toggleOpen(true);
|
|
25
|
-
};
|
|
26
|
-
const onClose = () => {
|
|
26
|
+
}, [onFocus, readOnly]);
|
|
27
|
+
const onClose = useCallback(() => {
|
|
27
28
|
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
28
29
|
toggleOpen(false);
|
|
29
|
-
};
|
|
30
|
-
const
|
|
31
|
-
if (open) {
|
|
32
|
-
onClose();
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
onOpen();
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
const { onChange, onClear, value } = useSelectValueControl({
|
|
30
|
+
}, [onBlur]);
|
|
31
|
+
const { onChange, onClear: onClearFromControl, value } = useSelectValueControl({
|
|
39
32
|
defaultValue,
|
|
40
33
|
mode,
|
|
41
34
|
onChange: onChangeProp,
|
|
@@ -43,9 +36,99 @@ const Select = forwardRef(function Select(props, ref) {
|
|
|
43
36
|
onClose,
|
|
44
37
|
value: valueProp,
|
|
45
38
|
});
|
|
39
|
+
// Wrap onClear and delegate to control hook
|
|
40
|
+
const onClear = useCallback((e) => {
|
|
41
|
+
onClearFromControl(e);
|
|
42
|
+
}, [onClearFromControl]);
|
|
46
43
|
const nodeRef = useRef(null);
|
|
47
|
-
const
|
|
48
|
-
|
|
44
|
+
const composedRef = useComposeRefs([ref, nodeRef]);
|
|
45
|
+
// Helper function to recursively add checkbox to all options in tree structure
|
|
46
|
+
const addCheckboxToTreeOptions = useCallback((opts) => {
|
|
47
|
+
return opts.map((opt) => ({
|
|
48
|
+
...opt,
|
|
49
|
+
showCheckbox: true,
|
|
50
|
+
checkSite: 'prefix',
|
|
51
|
+
children: opt.children
|
|
52
|
+
? addCheckboxToTreeOptions(opt.children)
|
|
53
|
+
: undefined,
|
|
54
|
+
}));
|
|
55
|
+
}, []);
|
|
56
|
+
const getAllDescendantIds = useCallback((option) => {
|
|
57
|
+
const ids = new Set();
|
|
58
|
+
const collect = (opt) => {
|
|
59
|
+
ids.add(String(opt.id));
|
|
60
|
+
if (opt.children && opt.children.length > 0) {
|
|
61
|
+
opt.children.forEach(collect);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
collect(option);
|
|
65
|
+
return Array.from(ids);
|
|
66
|
+
}, []);
|
|
67
|
+
const findOptionById = useCallback((id, opts) => {
|
|
68
|
+
for (const opt of opts) {
|
|
69
|
+
if (String(opt.id) === id) {
|
|
70
|
+
return opt;
|
|
71
|
+
}
|
|
72
|
+
if (opt.children) {
|
|
73
|
+
const found = findOptionById(id, opt.children);
|
|
74
|
+
if (found) {
|
|
75
|
+
return found;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}, []);
|
|
81
|
+
// Convert children (Option components) to DropdownOption format
|
|
82
|
+
// Or use provided options directly
|
|
83
|
+
const options = useMemo(() => {
|
|
84
|
+
// If options prop is provided, use it directly
|
|
85
|
+
if (optionsProp) {
|
|
86
|
+
// In tree mode (multiple mode with tree structure), ensure all options have checkbox
|
|
87
|
+
if (mode === 'multiple') {
|
|
88
|
+
const hasTreeStructure = optionsProp.some((opt) => opt.children && opt.children.length > 0);
|
|
89
|
+
if (hasTreeStructure) {
|
|
90
|
+
return addCheckboxToTreeOptions(optionsProp);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return optionsProp;
|
|
94
|
+
}
|
|
95
|
+
// Otherwise, convert children to options
|
|
96
|
+
if (!children)
|
|
97
|
+
return [];
|
|
98
|
+
return Children.toArray(children)
|
|
99
|
+
.filter((child) => {
|
|
100
|
+
var _a;
|
|
101
|
+
return (React.isValidElement(child) &&
|
|
102
|
+
(child.type === Option || ((_a = child.type) === null || _a === void 0 ? void 0 : _a.displayName) === 'Option'));
|
|
103
|
+
})
|
|
104
|
+
.map((child) => {
|
|
105
|
+
const props = child.props;
|
|
106
|
+
return {
|
|
107
|
+
id: props.value,
|
|
108
|
+
name: props.children,
|
|
109
|
+
showCheckbox: mode === 'multiple',
|
|
110
|
+
checkSite: mode === 'multiple' ? 'prefix' : 'suffix',
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
}, [children, mode, optionsProp, addCheckboxToTreeOptions]);
|
|
114
|
+
// Determine dropdown type based on options structure and mode
|
|
115
|
+
// Tree mode is only available in multiple mode
|
|
116
|
+
const dropdownType = useMemo(() => {
|
|
117
|
+
if (optionsProp && mode === 'multiple') {
|
|
118
|
+
// If options prop is provided and mode is multiple, check if it has tree structure
|
|
119
|
+
const hasTreeStructure = optionsProp.some((opt) => opt.children && opt.children.length > 0);
|
|
120
|
+
return hasTreeStructure ? 'tree' : type;
|
|
121
|
+
}
|
|
122
|
+
return type;
|
|
123
|
+
}, [optionsProp, type, mode]);
|
|
124
|
+
const dropdownValue = useMemo(() => {
|
|
125
|
+
if (!value)
|
|
126
|
+
return undefined;
|
|
127
|
+
if (Array.isArray(value)) {
|
|
128
|
+
return value.map((v) => String(v.id));
|
|
129
|
+
}
|
|
130
|
+
return String(value.id);
|
|
131
|
+
}, [value]);
|
|
49
132
|
function getPlaceholder() {
|
|
50
133
|
if (typeof renderValue === 'function') {
|
|
51
134
|
return renderValue(value);
|
|
@@ -55,23 +138,15 @@ const Select = forwardRef(function Select(props, ref) {
|
|
|
55
138
|
}
|
|
56
139
|
return placeholder;
|
|
57
140
|
}
|
|
58
|
-
useClickAway(() => {
|
|
59
|
-
if (!open)
|
|
60
|
-
return;
|
|
61
|
-
return () => {
|
|
62
|
-
onClose();
|
|
63
|
-
};
|
|
64
|
-
}, nodeRef, [nodeRef, open, toggleOpen]);
|
|
65
|
-
const onClickTextField = () => {
|
|
66
|
-
if (!disabled) {
|
|
67
|
-
onToggleOpen();
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
141
|
/**
|
|
71
142
|
* keyboard events for a11y
|
|
72
143
|
* (@todo keyboard event map into option selection when menu is opened)
|
|
73
144
|
*/
|
|
74
145
|
const onKeyDownTextField = (evt) => {
|
|
146
|
+
// Prevent keyboard events from opening when readOnly is true
|
|
147
|
+
if (readOnly) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
75
150
|
/** for a11y to open menu via keyboard */
|
|
76
151
|
switch (evt.code) {
|
|
77
152
|
case 'Enter':
|
|
@@ -94,23 +169,62 @@ const Select = forwardRef(function Select(props, ref) {
|
|
|
94
169
|
}
|
|
95
170
|
}
|
|
96
171
|
};
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
172
|
+
const handleDropdownSelect = useCallback((option) => {
|
|
173
|
+
if (mode === 'multiple' && dropdownType === 'tree') {
|
|
174
|
+
const onChangeMultiple = onChange;
|
|
175
|
+
const currentValues = Array.isArray(value) ? value : [];
|
|
176
|
+
const allDescendantIds = getAllDescendantIds(option);
|
|
177
|
+
const allDescendantValues = allDescendantIds.map((id) => {
|
|
178
|
+
const foundOption = findOptionById(id, options);
|
|
179
|
+
return {
|
|
180
|
+
id,
|
|
181
|
+
name: (foundOption === null || foundOption === void 0 ? void 0 : foundOption.name) || id,
|
|
182
|
+
};
|
|
183
|
+
});
|
|
184
|
+
const selectedDescendantIds = allDescendantIds.filter((id) => currentValues.some((v) => String(v.id) === id));
|
|
185
|
+
const allSelected = selectedDescendantIds.length === allDescendantIds.length;
|
|
186
|
+
if (allSelected) {
|
|
187
|
+
// Deselect all descendants in a single update
|
|
188
|
+
const descendantIdSet = new Set(allDescendantIds.map((id) => String(id)));
|
|
189
|
+
const nextValues = currentValues.filter((v) => !descendantIdSet.has(String(v.id)));
|
|
190
|
+
onChangeMultiple(nextValues);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
// Select all descendants that are not yet selected in a single update
|
|
194
|
+
const existingIdSet = new Set(currentValues.map((v) => String(v.id)));
|
|
195
|
+
const valuesToAdd = allDescendantValues.filter((descValue) => !existingIdSet.has(String(descValue.id)));
|
|
196
|
+
const nextValues = [...currentValues, ...valuesToAdd];
|
|
197
|
+
onChangeMultiple(nextValues);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// Normal selection logic for non-tree mode
|
|
202
|
+
const selectValue = {
|
|
203
|
+
id: String(option.id),
|
|
204
|
+
name: String(option.name),
|
|
205
|
+
};
|
|
206
|
+
if (mode === 'multiple') {
|
|
207
|
+
onChange(selectValue);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
onChange(selectValue);
|
|
211
|
+
onClose();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}, [mode, onChange, onClose, value, dropdownType, getAllDescendantIds, findOptionById, options]);
|
|
215
|
+
const handleVisibilityChange = useCallback((isOpen) => {
|
|
216
|
+
if (isOpen && readOnly) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (isOpen) {
|
|
220
|
+
onOpen();
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
onClose();
|
|
107
224
|
}
|
|
108
|
-
}, [
|
|
225
|
+
}, [onOpen, onClose, readOnly]);
|
|
109
226
|
const resolvedInputProps = {
|
|
110
227
|
...inputProps,
|
|
111
|
-
'aria-controls': MENU_ID,
|
|
112
|
-
'aria-expanded': open,
|
|
113
|
-
'aria-owns': MENU_ID,
|
|
114
228
|
placeholder: getPlaceholder(),
|
|
115
229
|
role: 'combobox',
|
|
116
230
|
};
|
|
@@ -118,7 +232,7 @@ const Select = forwardRef(function Select(props, ref) {
|
|
|
118
232
|
onChange,
|
|
119
233
|
value,
|
|
120
234
|
}), [onChange, value]);
|
|
121
|
-
return (jsx(SelectControlContext.Provider, { value: context, children:
|
|
235
|
+
return (jsx(SelectControlContext.Provider, { value: context, children: jsx("div", { ref: nodeRef, className: cx(selectClasses.host, fullWidth && selectClasses.hostFullWidth, mode && selectClasses.hostMode(mode)), children: jsx(Dropdown, { disabled: readOnly || disabled, maxHeight: menuMaxHeight, mode: mode, onScroll: onScroll, onSelect: handleDropdownSelect, onVisibilityChange: handleVisibilityChange, open: readOnly ? false : open, options: options, sameWidth: true, type: dropdownType, value: dropdownValue, zIndex: dropdownZIndex, globalPortal: globalPortal, children: jsx(SelectTrigger, { ref: composedRef, active: !readOnly && open, className: className, clearable: clearable, disabled: disabled, error: error, fullWidth: fullWidth, inputRef: inputRef, mode: mode, onTagClose: onChange, onClear: onClear, onKeyDown: onKeyDownTextField, prefix: prefix, readOnly: readOnly, ...(mode === 'single' && renderValue ? { renderValue } : {}), required: required, inputProps: resolvedInputProps, size: size, suffixActionIcon: suffixActionIcon, value: value === null ? undefined : value }) }) }) }));
|
|
122
236
|
});
|
|
123
237
|
|
|
124
238
|
export { Select as default };
|
package/Select/TreeSelect.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { SelectInputSize } from '@mezzanine-ui/core/select';
|
|
2
2
|
import { FormElementFocusHandlers } from '../Form';
|
|
3
3
|
import { MenuProps } from '../Menu';
|
|
4
|
-
import { PickRenameMulti } from '../utils/general';
|
|
5
|
-
import { InputTriggerPopperProps } from '../_internal/InputTriggerPopper';
|
|
6
|
-
import { SelectTriggerProps, SelectTriggerInputProps } from './SelectTrigger';
|
|
7
|
-
import { SelectValue, TreeSelectOption } from './typings';
|
|
8
4
|
import { TreeProps } from '../Tree';
|
|
5
|
+
import { InputTriggerPopperProps } from '../_internal/InputTriggerPopper';
|
|
6
|
+
import { PickRenameMulti } from '../utils/general';
|
|
7
|
+
import { SelectTriggerInputProps, SelectTriggerProps, SelectValue, TreeSelectOption } from './typings';
|
|
9
8
|
export interface TreeSelectProps extends Omit<SelectTriggerProps, 'active' | 'onBlur' | 'onChange' | 'onClear' | 'onClick' | 'onFocus' | 'onKeyDown' | 'readOnly' | 'searchInputProps'>, FormElementFocusHandlers, Pick<TreeProps, 'defaultExpandAll' | 'disabledValues' | 'expandControllerRef' | 'onExpand'>, PickRenameMulti<Pick<MenuProps, 'itemsInView' | 'maxHeight' | 'role' | 'size'>, {
|
|
10
9
|
maxHeight: 'menuMaxHeight';
|
|
11
10
|
role: 'menuRole';
|
|
@@ -38,6 +37,12 @@ export interface TreeSelectProps extends Omit<SelectTriggerProps, 'active' | 'on
|
|
|
38
37
|
* select input placeholder
|
|
39
38
|
*/
|
|
40
39
|
placeholder?: string;
|
|
40
|
+
/**
|
|
41
|
+
* To customize rendering select input value.
|
|
42
|
+
* For single mode, receives the first value from the array.
|
|
43
|
+
* For multiple mode, receives the full array.
|
|
44
|
+
*/
|
|
45
|
+
renderValue?: (value?: SelectValue | SelectValue[] | null) => string;
|
|
41
46
|
/**
|
|
42
47
|
* Whether the selection is required.
|
|
43
48
|
* @default false
|
|
@@ -63,5 +68,5 @@ export interface TreeSelectProps extends Omit<SelectTriggerProps, 'active' | 'on
|
|
|
63
68
|
*/
|
|
64
69
|
value?: SelectValue[];
|
|
65
70
|
}
|
|
66
|
-
declare const TreeSelect: import("react").ForwardRefExoticComponent<
|
|
71
|
+
declare const TreeSelect: import("react").ForwardRefExoticComponent<TreeSelectProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
67
72
|
export default TreeSelect;
|
package/Select/TreeSelect.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { forwardRef, useContext, useMemo, useRef, useState } from 'react';
|
|
4
3
|
import { selectClasses } from '@mezzanine-ui/core/select';
|
|
5
|
-
import {
|
|
4
|
+
import { forwardRef, useContext, useMemo, useRef, useState } from 'react';
|
|
6
5
|
import { useClickAway } from '../hooks/useClickAway.js';
|
|
7
|
-
import
|
|
6
|
+
import { useComposeRefs } from '../hooks/useComposeRefs.js';
|
|
8
7
|
import { useIsomorphicLayoutEffect } from '../hooks/useIsomorphicLayoutEffect.js';
|
|
8
|
+
import SelectTrigger from './SelectTrigger.js';
|
|
9
9
|
import { FormControlContext } from '../Form/FormControlContext.js';
|
|
10
10
|
import { traverseTree } from '../Tree/traverseTree.js';
|
|
11
11
|
import InputTriggerPopper from '../_internal/InputTriggerPopper/InputTriggerPopper.js';
|
|
@@ -15,6 +15,7 @@ import { toggleValue } from '../Tree/toggleValue.js';
|
|
|
15
15
|
import cx from 'clsx';
|
|
16
16
|
|
|
17
17
|
const TreeSelect = forwardRef((props, ref) => {
|
|
18
|
+
var _a;
|
|
18
19
|
const { disabled: disabledFromFormControl, fullWidth: fullWidthFromFormControl, required: requiredFromFormControl, severity, } = useContext(FormControlContext) || {};
|
|
19
20
|
const { className, clearable = false, defaultExpandAll, depth, disabled = disabledFromFormControl || false, disabledValues, error = severity === 'error' || false, expandControllerRef, fullWidth = fullWidthFromFormControl || false, inputProps, inputRef, itemsInView = 4, menuMaxHeight, menuProps, menuRole = 'listbox', menuSize, mode = 'single', onBlur, onChange: onChangeProp, onExpand: onExpandProp, onFocus, options, placeholder = '', popperOptions, prefix, renderValue, required = requiredFromFormControl || false, sameWidth = false, size, suffixActionIcon, treeProps, value: valueProp, } = props;
|
|
20
21
|
const { className: treeClassName, ...restTreeProps } = treeProps || {};
|
|
@@ -54,7 +55,7 @@ const TreeSelect = forwardRef((props, ref) => {
|
|
|
54
55
|
const controllerRef = useRef(null);
|
|
55
56
|
useIsomorphicLayoutEffect(() => {
|
|
56
57
|
var _a, _b;
|
|
57
|
-
(_b = (_a = controllerRef.current) === null || _a === void 0 ? void 0 : _a.
|
|
58
|
+
(_b = (_a = controllerRef.current) === null || _a === void 0 ? void 0 : _a.update) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
58
59
|
}, [valueProp]);
|
|
59
60
|
/** Open control */
|
|
60
61
|
const [open, toggleOpen] = useState(false);
|
|
@@ -188,7 +189,13 @@ const TreeSelect = forwardRef((props, ref) => {
|
|
|
188
189
|
setExpandedValues(newExpandedValues);
|
|
189
190
|
onExpandProp === null || onExpandProp === void 0 ? void 0 : onExpandProp(value);
|
|
190
191
|
};
|
|
191
|
-
|
|
192
|
+
// Convert valueProp to single value for single mode
|
|
193
|
+
const triggerValue = multiple ? valueProp : ((_a = valueProp === null || valueProp === void 0 ? void 0 : valueProp[0]) !== null && _a !== void 0 ? _a : undefined);
|
|
194
|
+
// Adapt renderValue for single mode
|
|
195
|
+
const adaptedRenderValue = renderValue && !multiple
|
|
196
|
+
? (value) => renderValue(value !== null && value !== void 0 ? value : null)
|
|
197
|
+
: undefined;
|
|
198
|
+
return (jsxs("div", { ref: nodeRef, className: selectClasses.treeSelect, children: [jsx(SelectTrigger, { ref: composedRef, active: open, className: className, clearable: clearable, disabled: disabled, error: error, fullWidth: fullWidth, inputProps: resolvedInputProps, inputRef: inputRef, mode: mode, onClear: onClear, onClick: onTextFieldClick, onKeyDown: onTextFieldKeydown, onTagClose: onTagClose, prefix: prefix, readOnly: true, ...(mode === 'single' && adaptedRenderValue ? { renderValue: adaptedRenderValue } : {}), required: required, size: size, suffixActionIcon: suffixActionIcon, value: triggerValue }), jsx(InputTriggerPopper, { ref: popperRef, anchor: controlRef, className: selectClasses.popper, controllerRef: controllerRef, open: open, options: popperOptions, sameWidth: sameWidth, children: jsx(Menu, { itemsInView: itemsInView, maxHeight: menuMaxHeight, role: menuRole, size: menuSize, style: {
|
|
192
199
|
...restStyle,
|
|
193
200
|
border: border || 0,
|
|
194
201
|
width: width || `${panelWidth}px`,
|
package/Select/index.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { default as OptionGroup } from '../Menu/MenuItemGroup';
|
|
2
|
+
export type { MenuItemGroupProps as OptionGroupProps } from '../Menu/MenuItemGroup';
|
|
3
|
+
export { default as Option } from './Option';
|
|
4
|
+
export type { OptionProps } from './Option';
|
|
5
|
+
export { default } from './Select';
|
|
6
|
+
export type { SelectProps } from './Select';
|
|
2
7
|
export { SelectControlContext } from './SelectControlContext';
|
|
3
8
|
export { default as SelectTrigger } from './SelectTrigger';
|
|
4
|
-
export type { SelectTriggerProps, SelectTriggerInputProps, } from './SelectTrigger';
|
|
5
9
|
export { default as SelectTriggerTags } from './SelectTriggerTags';
|
|
6
10
|
export type { SelectTriggerTagsProps } from './SelectTriggerTags';
|
|
7
|
-
export type { SelectProps } from './Select';
|
|
8
|
-
export { default } from './Select';
|
|
9
|
-
export { default as Option } from './Option';
|
|
10
|
-
export type { OptionProps } from './Option';
|
|
11
|
-
export { default as OptionGroup } from '../Menu/MenuItemGroup';
|
|
12
|
-
export type { MenuItemGroupProps as OptionGroupProps } from '../Menu/MenuItemGroup';
|
|
13
|
-
export type { TreeSelectProps } from './TreeSelect';
|
|
14
11
|
export { default as TreeSelect } from './TreeSelect';
|
|
12
|
+
export type { TreeSelectProps } from './TreeSelect';
|
|
13
|
+
export * from './typings';
|
package/Select/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
export { default as OptionGroup } from '../Menu/MenuItemGroup.js';
|
|
2
|
+
export { default as Option } from './Option.js';
|
|
3
|
+
export { default } from './Select.js';
|
|
1
4
|
export { SelectControlContext } from './SelectControlContext.js';
|
|
2
5
|
export { default as SelectTrigger } from './SelectTrigger.js';
|
|
3
6
|
export { default as SelectTriggerTags } from './SelectTriggerTags.js';
|
|
4
|
-
export { default } from './Select.js';
|
|
5
|
-
export { default as Option } from './Option.js';
|
|
6
|
-
export { default as OptionGroup } from '../Menu/MenuItemGroup.js';
|
|
7
7
|
export { default as TreeSelect } from './TreeSelect.js';
|
|
@@ -1,33 +1,35 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { timePanelClasses } from '@mezzanine-ui/core/time-panel';
|
|
3
|
-
import { forwardRef, useRef, useEffect } from 'react';
|
|
3
|
+
import { forwardRef, useRef, useCallback, useEffect } from 'react';
|
|
4
|
+
import { getNumericCSSVariablePixelValue } from '../utils/get-css-variable-value.js';
|
|
5
|
+
import Scrollbar from '../Scrollbar/Scrollbar.js';
|
|
4
6
|
import cx from 'clsx';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* The react component for `mezzanine` time panel column.
|
|
8
10
|
*/
|
|
9
11
|
const TimePanelColumn = forwardRef(function TimePanelColumn(props, ref) {
|
|
10
|
-
const { activeUnit, cellHeight
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
onChange(unit);
|
|
17
|
-
};
|
|
18
|
-
};
|
|
12
|
+
const { activeUnit, cellHeight: cellHeightProp, onChange, units } = props;
|
|
13
|
+
const cellHeight = cellHeightProp !== null && cellHeightProp !== void 0 ? cellHeightProp : getNumericCSSVariablePixelValue('--mzn-spacing-size-element-loose');
|
|
14
|
+
const viewportRef = useRef(null);
|
|
15
|
+
const getChangeHandler = useCallback((unit) => () => {
|
|
16
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(unit);
|
|
17
|
+
}, [onChange]);
|
|
19
18
|
const preferSmoothScrollRef = useRef(true);
|
|
20
19
|
useEffect(() => {
|
|
21
20
|
const activeIndex = units.findIndex(({ value }) => value === activeUnit);
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
top: activeIndex * cellHeight, // (activeIndex - 3) * cellHeight, (center)
|
|
21
|
+
if (viewportRef.current) {
|
|
22
|
+
viewportRef.current.scrollTo({
|
|
25
23
|
behavior: preferSmoothScrollRef.current ? 'auto' : 'smooth',
|
|
24
|
+
top: activeIndex * cellHeight, // (activeIndex - 3) * cellHeight, (center)
|
|
26
25
|
});
|
|
27
26
|
}
|
|
28
27
|
preferSmoothScrollRef.current = false;
|
|
29
28
|
}, [activeUnit, cellHeight, units]);
|
|
30
|
-
|
|
29
|
+
const handleViewportReady = useCallback((viewport) => {
|
|
30
|
+
viewportRef.current = viewport;
|
|
31
|
+
}, []);
|
|
32
|
+
return (jsx("div", { ref: ref, className: timePanelClasses.column, children: jsx(Scrollbar, { maxHeight: cellHeight * 7, onViewportReady: handleViewportReady, children: units.map((unit) => (jsx("button", { type: "button", className: cx(timePanelClasses.button, timePanelClasses.columnButton, {
|
|
31
33
|
[timePanelClasses.buttonActive]: unit.value === activeUnit,
|
|
32
34
|
}), onClick: getChangeHandler(unit), children: unit.label }, unit.value))) }) }));
|
|
33
35
|
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { RangePickerTriggerProps } from '../Picker';
|
|
2
|
+
import { TimeRangePickerValue } from './useTimeRangePickerValue';
|
|
3
|
+
import { TimePickerPanelProps } from '../TimePicker/TimePickerPanel';
|
|
4
|
+
export interface TimeRangePickerProps extends Pick<TimePickerPanelProps, 'fadeProps' | 'hideHour' | 'hideMinute' | 'hideSecond' | 'hourStep' | 'minuteStep' | 'popperProps' | 'secondStep'>, Pick<RangePickerTriggerProps, 'className' | 'clearable' | 'disabled' | 'error' | 'errorMessagesFrom' | 'errorMessagesTo' | 'fullWidth' | 'inputFromPlaceholder' | 'inputFromProps' | 'inputToPlaceholder' | 'inputToProps' | 'prefix' | 'readOnly' | 'required' | 'size' | 'validateFrom' | 'validateTo'> {
|
|
5
|
+
/**
|
|
6
|
+
* The format for displaying time.
|
|
7
|
+
* @default 'HH:mm:ss' or 'HH:mm' based on hideSecond
|
|
8
|
+
*/
|
|
9
|
+
format?: string;
|
|
10
|
+
/**
|
|
11
|
+
* A function that fires when panel toggle. Receive open status in boolean format as props.
|
|
12
|
+
*/
|
|
13
|
+
onPanelToggle?: (open: boolean) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Change handler. Takes an array of your declared `DateType` which represents from and to in order.
|
|
16
|
+
*/
|
|
17
|
+
onChange?: (target?: TimeRangePickerValue) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Value of the range picker.
|
|
20
|
+
* It is an array of your declared `DateType` which represents from and to in order.
|
|
21
|
+
*/
|
|
22
|
+
value?: TimeRangePickerValue;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The react component for `mezzanine` time range picker.
|
|
26
|
+
* Notice that any component related to time-range-picker should be used along with `CalendarContext`.
|
|
27
|
+
*/
|
|
28
|
+
declare const TimeRangePicker: import("react").ForwardRefExoticComponent<TimeRangePickerProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
29
|
+
export default TimeRangePicker;
|