@mezzanine-ui/react 1.0.0-rc.0 → 1.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/Badge/Badge.d.ts +4 -0
  2. package/Badge/Badge.js +2 -2
  3. package/Badge/typings.d.ts +13 -1
  4. package/Calendar/CalendarDays.js +4 -3
  5. package/Calendar/CalendarWeeks.js +4 -3
  6. package/Cascader/Cascader.d.ts +3 -0
  7. package/Cascader/Cascader.js +241 -0
  8. package/Cascader/CascaderPanel.d.ts +29 -0
  9. package/Cascader/CascaderPanel.js +29 -0
  10. package/Cascader/index.d.ts +5 -0
  11. package/Cascader/index.js +2 -0
  12. package/Cascader/typings.d.ts +92 -0
  13. package/Description/Description.d.ts +6 -1
  14. package/Description/Description.js +11 -4
  15. package/Description/DescriptionContent.d.ts +9 -3
  16. package/Description/DescriptionContent.js +4 -1
  17. package/Description/DescriptionContext.d.ts +6 -0
  18. package/Description/DescriptionContext.js +9 -0
  19. package/Description/index.d.ts +2 -0
  20. package/Description/index.js +1 -0
  21. package/Form/FormField.d.ts +6 -0
  22. package/Form/FormField.js +2 -2
  23. package/Form/FormHintText.d.ts +12 -0
  24. package/Form/FormHintText.js +3 -2
  25. package/Layout/Layout.d.ts +21 -5
  26. package/Layout/Layout.js +23 -19
  27. package/Layout/LayoutContext.d.ts +6 -6
  28. package/Layout/LayoutContext.js +2 -2
  29. package/Layout/LayoutHost.d.ts +0 -4
  30. package/Layout/LayoutHost.js +16 -13
  31. package/Layout/LayoutLeftPanel.d.ts +19 -0
  32. package/Layout/LayoutLeftPanel.js +86 -0
  33. package/Layout/LayoutMain.d.ts +10 -1
  34. package/Layout/LayoutMain.js +12 -3
  35. package/Layout/LayoutRightPanel.d.ts +19 -0
  36. package/Layout/{LayoutSidePanel.js → LayoutRightPanel.js} +32 -36
  37. package/Layout/index.d.ts +2 -2
  38. package/Layout/index.js +2 -1
  39. package/Modal/MediaPreviewModal.d.ts +4 -0
  40. package/Modal/MediaPreviewModal.js +2 -2
  41. package/Modal/Modal.d.ts +4 -0
  42. package/Modal/Modal.js +2 -2
  43. package/Modal/useModalContainer.js +0 -1
  44. package/Navigation/Navigation.d.ts +4 -0
  45. package/Navigation/Navigation.js +39 -3
  46. package/Navigation/NavigationFooter.js +19 -2
  47. package/Navigation/NavigationOption.d.ts +4 -0
  48. package/Navigation/NavigationOption.js +40 -19
  49. package/Navigation/NavigationOverflowMenuOption.js +11 -7
  50. package/Navigation/NavigationUserMenu.d.ts +1 -0
  51. package/Navigation/NavigationUserMenu.js +24 -5
  52. package/Navigation/context.d.ts +2 -0
  53. package/Navigation/context.js +4 -1
  54. package/Picker/RangePickerTrigger.js +1 -1
  55. package/Section/Section.js +6 -6
  56. package/Transition/Collapse.d.ts +2 -1
  57. package/Transition/Collapse.js +2 -1
  58. package/Upload/Upload.js +63 -9
  59. package/Upload/UploadPictureCard.d.ts +25 -15
  60. package/Upload/UploadPictureCard.js +14 -6
  61. package/index.d.ts +4 -2
  62. package/index.js +4 -1
  63. package/package.json +4 -4
  64. package/Layout/LayoutSidePanel.d.ts +0 -14
package/Badge/Badge.d.ts CHANGED
@@ -6,24 +6,28 @@ declare const Badge: import("react").ForwardRefExoticComponent<(Omit<Omit<Native
6
6
  children?: never;
7
7
  count: number;
8
8
  overflowCount?: number;
9
+ size?: never;
9
10
  text?: never;
10
11
  variant: BadgeCountVariant;
11
12
  }, "ref"> | Omit<Omit<NativeElementPropsWithoutKeyAndRef<"span">, "children"> & {
12
13
  children?: never;
13
14
  count?: never;
14
15
  overflowCount?: never;
16
+ size?: import("@mezzanine-ui/core/badge").BadgeTextSize;
15
17
  text?: string;
16
18
  variant: import("@mezzanine-ui/core/badge").BadgeDotVariant;
17
19
  }, "ref"> | Omit<Omit<NativeElementPropsWithoutKeyAndRef<"span">, "children"> & {
18
20
  children?: import("react").ReactNode;
19
21
  count?: never;
20
22
  overflowCount?: never;
23
+ size?: never;
21
24
  text?: never;
22
25
  variant: import("@mezzanine-ui/core/badge").BadgeDotVariant;
23
26
  }, "ref"> | Omit<Omit<NativeElementPropsWithoutKeyAndRef<"span">, "children"> & {
24
27
  children?: never;
25
28
  count?: never;
26
29
  overflowCount?: never;
30
+ size?: import("@mezzanine-ui/core/badge").BadgeTextSize;
27
31
  text: string;
28
32
  variant: import("@mezzanine-ui/core/badge").BadgeTextVariant;
29
33
  }, "ref">) & import("react").RefAttributes<HTMLSpanElement>>;
package/Badge/Badge.js CHANGED
@@ -14,8 +14,8 @@ const isCountVariant = (variant) => [
14
14
  * The react component for `mezzanine` badge.
15
15
  */
16
16
  const Badge = forwardRef(function Badge(props, ref) {
17
- const { children, count, className, overflowCount, text, variant, ...rest } = props;
18
- return (jsxs("div", { className: badgeClasses.container(!!children), children: [children, jsx("span", { ...rest, ref: ref, className: cx(badgeClasses.host, badgeClasses.variant(variant), { [badgeClasses.hide]: isCountVariant(variant) && count === 0 }, className), children: isCountVariant(variant)
17
+ const { children, count, className, overflowCount, size, text, variant, ...rest } = props;
18
+ return (jsxs("div", { className: badgeClasses.container(!!children), children: [children, jsx("span", { ...rest, ref: ref, className: cx(badgeClasses.host, badgeClasses.variant(variant), { [badgeClasses.hide]: isCountVariant(variant) && count === 0 }, size && badgeClasses.size(size), className), children: isCountVariant(variant)
19
19
  ? overflowCount && count > overflowCount
20
20
  ? `${overflowCount}+`
21
21
  : count
@@ -1,4 +1,4 @@
1
- import { BadgeCountVariant, BadgeDotVariant, BadgeTextVariant } from '@mezzanine-ui/core/badge';
1
+ import { BadgeCountVariant, BadgeDotVariant, BadgeTextSize, BadgeTextVariant } from '@mezzanine-ui/core/badge';
2
2
  import { ReactNode } from 'react';
3
3
  import { NativeElementPropsWithoutKeyAndRef } from 'react/src/utils/jsx-types';
4
4
  export type BadgeProps = Omit<NativeElementPropsWithoutKeyAndRef<'span'>, 'children'> & BadgeVariantProps;
@@ -21,6 +21,11 @@ type BadgeCountProps = {
21
21
  * it will show overflowCount suffixed with a "+".
22
22
  */
23
23
  overflowCount?: number;
24
+ /**
25
+ * ONLY AVAILABLE FOR DOT WITH TEXT BADGE.
26
+ * Controls the size of the dot and text.
27
+ */
28
+ size?: never;
24
29
  /**
25
30
  * ONLY AVAILABLE FOR DOT WITH TEXT BADGE.
26
31
  * String displayed next to the dot badge.
@@ -35,6 +40,7 @@ type BadgeTextProps = {
35
40
  children?: never;
36
41
  count?: never;
37
42
  overflowCount?: never;
43
+ size?: BadgeTextSize;
38
44
  text: string;
39
45
  variant: BadgeTextVariant;
40
46
  };
@@ -42,6 +48,11 @@ type BadgeDotWithTextProps = {
42
48
  children?: never;
43
49
  count?: never;
44
50
  overflowCount?: never;
51
+ /**
52
+ * Controls the size of the text.
53
+ * @default 'main'
54
+ */
55
+ size?: BadgeTextSize;
45
56
  text?: string;
46
57
  variant: BadgeDotVariant;
47
58
  };
@@ -49,6 +60,7 @@ type BadgeDotProps = {
49
60
  children?: ReactNode;
50
61
  count?: never;
51
62
  overflowCount?: never;
63
+ size?: never;
52
64
  text?: never;
53
65
  variant: BadgeDotVariant;
54
66
  };
@@ -14,10 +14,11 @@ import cx from 'clsx';
14
14
  * You may use it to compose your own calendar.
15
15
  */
16
16
  function CalendarDays(props) {
17
- const { locale, getCalendarGrid, getDate, getMonth, getNow, isDateIncluded, isSameDate, setDate, setMonth, setHour, setMinute, setSecond, setMillisecond, } = useCalendarContext();
17
+ const { locale, getCalendarGrid, getDate, getMonth, getNow, getWeekends, isDateIncluded, isSameDate, setDate, setMonth, setHour, setMinute, setSecond, setMillisecond, } = useCalendarContext();
18
18
  const { className, displayWeekDayLocale = locale, isYearDisabled, isMonthDisabled, isDateDisabled, isDateInRange, onClick: onClickProp, onDateHover, renderAnnotations, referenceDate, value, ...rest } = props;
19
+ const weekends = useMemo(() => getWeekends(displayWeekDayLocale), [getWeekends, displayWeekDayLocale]);
19
20
  const daysGrid = useMemo(() => getCalendarGrid(referenceDate, displayWeekDayLocale), [getCalendarGrid, displayWeekDayLocale, referenceDate]);
20
- return (jsx("div", { ...rest, className: cx(calendarClasses.board, className), children: jsxs("div", { className: calendarClasses.daysGrid, children: [jsx(CalendarDayOfWeek, { displayWeekDayLocale: displayWeekDayLocale }), daysGrid.map((week, index) => (jsx("div", { className: calendarClasses.row, children: week.map((dateNum) => {
21
+ return (jsx("div", { ...rest, className: cx(calendarClasses.board, className), children: jsxs("div", { className: calendarClasses.daysGrid, children: [jsx(CalendarDayOfWeek, { displayWeekDayLocale: displayWeekDayLocale }), daysGrid.map((week, index) => (jsx("div", { className: calendarClasses.row, children: week.map((dateNum, dayIndex) => {
21
22
  const isPrevMonth = index === 0 && dateNum > 7;
22
23
  const isNextMonth = index > 3 && dateNum <= 14;
23
24
  const thisMonth = getMonth(referenceDate);
@@ -66,7 +67,7 @@ function CalendarDays(props) {
66
67
  ]
67
68
  .filter(Boolean)
68
69
  .join(', ');
69
- return (jsx(CalendarCell, { mode: "day", today: isSameDate(date, getNow()), active: active, disabled: isPrevMonth || isNextMonth, withAnnotation: Boolean(renderAnnotations), isRangeStart: inRangeStart, isRangeEnd: inRangeEnd, children: jsxs("button", { type: "button", "aria-disabled": disabled, disabled: disabled, "aria-label": ariaLabel, "aria-pressed": active, "aria-current": isToday ? 'date' : undefined, onMouseEnter: onMouseEnter, className: cx(calendarClasses.button, {
70
+ return (jsx(CalendarCell, { active: active, disabled: isPrevMonth || isNextMonth, isRangeEnd: inRangeEnd, isRangeStart: inRangeStart, isWeekend: weekends[dayIndex], mode: "day", today: isSameDate(date, getNow()), withAnnotation: Boolean(renderAnnotations), children: jsxs("button", { type: "button", "aria-disabled": disabled, disabled: disabled, "aria-label": ariaLabel, "aria-pressed": active, "aria-current": isToday ? 'date' : undefined, onMouseEnter: onMouseEnter, className: cx(calendarClasses.button, {
70
71
  [calendarClasses.buttonInRange]: inRange,
71
72
  [calendarClasses.buttonActive]: active,
72
73
  [calendarClasses.buttonDisabled]: disabled,
@@ -13,8 +13,9 @@ import cx from 'clsx';
13
13
  * You may use it to compose your own calendar.
14
14
  */
15
15
  function CalendarWeeks(props) {
16
- const { locale, getCalendarGrid, getWeek, getDate, getMonth, getNow, isInMonth, isSameDate, isWeekIncluded, setDate, setMonth, setHour, setMinute, setSecond, setMillisecond, getCurrentWeekFirstDate, } = useCalendarContext();
16
+ const { locale, getCalendarGrid, getWeek, getDate, getMonth, getNow, getWeekends, isInMonth, isSameDate, isWeekIncluded, setDate, setMonth, setHour, setMinute, setSecond, setMillisecond, getCurrentWeekFirstDate, } = useCalendarContext();
17
17
  const { className, displayWeekDayLocale = locale, isYearDisabled, isMonthDisabled, isWeekDisabled, isWeekInRange, onClick: onClickProp, onWeekHover, referenceDate, value, ...rest } = props;
18
+ const weekends = useMemo(() => getWeekends(displayWeekDayLocale), [getWeekends, displayWeekDayLocale]);
18
19
  const daysGrid = useMemo(() => getCalendarGrid(referenceDate, displayWeekDayLocale), [getCalendarGrid, referenceDate, displayWeekDayLocale]);
19
20
  // Pre-calculate all weeks data including dates and week first dates
20
21
  const weeksData = useMemo(() => {
@@ -143,8 +144,8 @@ function CalendarWeeks(props) {
143
144
  isSameDate(currentDate, lastWeekDatesMap.lastWeekDates[6]);
144
145
  cellActive = isFirstWeekFirstDate || isLastWeekLastDate;
145
146
  }
146
- return (jsx(CalendarCell, { mode: "week", today: isSameDate(dates[dateIndex], getNow()), disabled: disabled ||
147
- !isInMonth(dates[dateIndex], getMonth(referenceDate)), active: cellActive, isRangeStart: isFirstWeekFirstDate, isRangeEnd: isLastWeekLastDate, children: jsx("div", { className: cx(calendarClasses.button, {
147
+ return (jsx(CalendarCell, { active: cellActive, disabled: disabled ||
148
+ !isInMonth(dates[dateIndex], getMonth(referenceDate)), isRangeEnd: isLastWeekLastDate, isRangeStart: isFirstWeekFirstDate, isWeekend: weekends[dateIndex], mode: "week", today: isSameDate(dates[dateIndex], getNow()), children: jsx("div", { className: cx(calendarClasses.button, {
148
149
  [calendarClasses.buttonInRange]: weekIncluded,
149
150
  [calendarClasses.buttonActive]: cellActive,
150
151
  }), style: {
@@ -0,0 +1,3 @@
1
+ import { CascaderProps } from './typings';
2
+ declare const Cascader: import("react").ForwardRefExoticComponent<CascaderProps & import("react").RefAttributes<HTMLDivElement>>;
3
+ export default Cascader;
@@ -0,0 +1,241 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { forwardRef, useContext, useState, useRef, useCallback, useMemo, createElement } from 'react';
4
+ import { cascaderClasses } from '@mezzanine-ui/core/cascader';
5
+ import { offset } from '@floating-ui/react-dom';
6
+ import { MOTION_EASING, MOTION_DURATION } from '@mezzanine-ui/system/motion';
7
+ import { TransitionGroup } from 'react-transition-group';
8
+ import { useControlValueState } from '../Form/useControlValueState.js';
9
+ import { useDocumentEvents } from '../hooks/useDocumentEvents.js';
10
+ import SelectTrigger from '../Select/SelectTrigger.js';
11
+ import Translate from '../Transition/Translate.js';
12
+ import CascaderPanel from './CascaderPanel.js';
13
+ import { FormControlContext } from '../Form/FormControlContext.js';
14
+ import Popper from '../Popper/Popper.js';
15
+ import cx from 'clsx';
16
+
17
+ /**
18
+ * Walks the options tree using ids from `value` and returns a new activePath
19
+ * whose items carry proper `children` references from the tree.
20
+ * Items in `value` may omit `children`, so we cannot rely on them directly
21
+ * for panel expansion.
22
+ */
23
+ function resolveActivePath(options, value) {
24
+ const result = [];
25
+ let currentOptions = options;
26
+ for (const selectedItem of value) {
27
+ const found = currentOptions.find((o) => o.id === selectedItem.id);
28
+ if (!found)
29
+ break;
30
+ result.push(found);
31
+ if (found.children && found.children.length > 0) {
32
+ currentOptions = found.children;
33
+ }
34
+ else {
35
+ break;
36
+ }
37
+ }
38
+ return result;
39
+ }
40
+ const Cascader = forwardRef(function Cascader(props, ref) {
41
+ var _a, _b;
42
+ const { disabled: disabledFromFormControl, fullWidth: fullWidthFromFormControl, required: requiredFromFormControl, severity, } = useContext(FormControlContext) || {};
43
+ const { className, clearable = false, defaultValue, disabled = disabledFromFormControl || false, dropdownZIndex, error = severity === 'error' || false, fullWidth = fullWidthFromFormControl || false, globalPortal = true, menuMaxHeight, onBlur, onChange: onChangeProp, onFocus, options, placeholder = '', readOnly = false, required = requiredFromFormControl || false, size, value: valueProp, } = props;
44
+ const [open, setOpen] = useState(false);
45
+ const [activePath, setActivePath] = useState([]);
46
+ const [keyboardFocusedIndex, setKeyboardFocusedIndex] = useState(-1);
47
+ const [value, setValue] = useControlValueState({
48
+ defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : [],
49
+ value: valueProp,
50
+ });
51
+ const anchorRef = useRef(null);
52
+ const dropdownRef = useRef(null);
53
+ const handleOpen = useCallback(() => {
54
+ if (readOnly || disabled)
55
+ return;
56
+ setActivePath(resolveActivePath(options, value));
57
+ onFocus === null || onFocus === void 0 ? void 0 : onFocus();
58
+ setOpen(true);
59
+ }, [disabled, onFocus, options, readOnly, value]);
60
+ const handleClose = useCallback(() => {
61
+ onBlur === null || onBlur === void 0 ? void 0 : onBlur();
62
+ setOpen(false);
63
+ setKeyboardFocusedIndex(-1);
64
+ }, [onBlur]);
65
+ const handleClear = useCallback((event) => {
66
+ event.stopPropagation();
67
+ setValue([]);
68
+ onChangeProp === null || onChangeProp === void 0 ? void 0 : onChangeProp([]);
69
+ if (open) {
70
+ handleClose();
71
+ }
72
+ }, [handleClose, onChangeProp, open, setValue]);
73
+ const handleItemSelect = useCallback((panelIndex, option, isLeaf) => {
74
+ const newActivePath = [...activePath.slice(0, panelIndex), option];
75
+ setActivePath(newActivePath);
76
+ if (isLeaf) {
77
+ setValue(newActivePath);
78
+ onChangeProp === null || onChangeProp === void 0 ? void 0 : onChangeProp(newActivePath);
79
+ handleClose();
80
+ }
81
+ else {
82
+ setKeyboardFocusedIndex(-1);
83
+ }
84
+ }, [activePath, handleClose, onChangeProp, setValue]);
85
+ const panels = useMemo(() => {
86
+ const result = [options];
87
+ for (const activeOption of activePath) {
88
+ if (activeOption.children && activeOption.children.length > 0) {
89
+ result.push(activeOption.children);
90
+ }
91
+ else {
92
+ break;
93
+ }
94
+ }
95
+ return result;
96
+ }, [activePath, options]);
97
+ useDocumentEvents(() => {
98
+ if (!open)
99
+ return;
100
+ const handleClickAway = (event) => {
101
+ const target = event.target;
102
+ if (!target)
103
+ return;
104
+ const anchor = anchorRef.current;
105
+ const dropdown = dropdownRef.current;
106
+ if ((anchor === null || anchor === void 0 ? void 0 : anchor.contains(target)) || (dropdown === null || dropdown === void 0 ? void 0 : dropdown.contains(target)))
107
+ return;
108
+ handleClose();
109
+ };
110
+ return {
111
+ click: handleClickAway,
112
+ touchend: handleClickAway,
113
+ };
114
+ }, [handleClose, open]);
115
+ useDocumentEvents(() => {
116
+ if (!open)
117
+ return;
118
+ const currentPanelOptions = panels[panels.length - 1];
119
+ return {
120
+ keydown(event) {
121
+ switch (event.key) {
122
+ case 'Escape': {
123
+ event.preventDefault();
124
+ handleClose();
125
+ break;
126
+ }
127
+ case 'ArrowDown': {
128
+ event.preventDefault();
129
+ let next = keyboardFocusedIndex + 1;
130
+ while (next < currentPanelOptions.length &&
131
+ currentPanelOptions[next].disabled) {
132
+ next++;
133
+ }
134
+ if (next < currentPanelOptions.length) {
135
+ setKeyboardFocusedIndex(next);
136
+ }
137
+ break;
138
+ }
139
+ case 'ArrowUp': {
140
+ event.preventDefault();
141
+ let prev = keyboardFocusedIndex === -1
142
+ ? currentPanelOptions.length - 1
143
+ : keyboardFocusedIndex - 1;
144
+ while (prev >= 0 && currentPanelOptions[prev].disabled) {
145
+ prev--;
146
+ }
147
+ if (prev >= 0) {
148
+ setKeyboardFocusedIndex(prev);
149
+ }
150
+ break;
151
+ }
152
+ case 'ArrowRight':
153
+ case 'Enter':
154
+ case ' ': {
155
+ if (keyboardFocusedIndex === -1)
156
+ return;
157
+ const focusedOption = currentPanelOptions[keyboardFocusedIndex];
158
+ if (!focusedOption || focusedOption.disabled)
159
+ return;
160
+ const isLeaf = !focusedOption.children || focusedOption.children.length === 0;
161
+ if (event.key === 'ArrowRight' && isLeaf)
162
+ return;
163
+ event.preventDefault();
164
+ handleItemSelect(panels.length - 1, focusedOption, isLeaf);
165
+ break;
166
+ }
167
+ case 'ArrowLeft': {
168
+ event.preventDefault();
169
+ if (activePath.length === 0)
170
+ return;
171
+ const removedItem = activePath[activePath.length - 1];
172
+ const parentPanel = panels[activePath.length - 1];
173
+ const idx = parentPanel.findIndex((o) => o.id === removedItem.id);
174
+ setActivePath(activePath.slice(0, -1));
175
+ setKeyboardFocusedIndex(idx >= 0 ? idx : -1);
176
+ break;
177
+ }
178
+ }
179
+ },
180
+ };
181
+ }, [
182
+ activePath,
183
+ handleClose,
184
+ handleItemSelect,
185
+ keyboardFocusedIndex,
186
+ open,
187
+ panels,
188
+ ]);
189
+ const displayPath = open ? activePath : value;
190
+ const displayString = displayPath.map((o) => o.name).join(' / ');
191
+ const triggerValue = useMemo(() => {
192
+ if (displayPath.length === 0)
193
+ return undefined;
194
+ return { id: 'cascader-value', name: displayString };
195
+ }, [displayPath.length, displayString]);
196
+ const isPartial = open &&
197
+ activePath.length > 0 &&
198
+ !!((_b = (_a = activePath[activePath.length - 1]) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.length);
199
+ const zIndexMiddleware = useMemo(() => ({
200
+ name: 'zIndex',
201
+ fn: ({ elements }) => {
202
+ const val = dropdownZIndex !== null && dropdownZIndex !== void 0 ? dropdownZIndex : 1;
203
+ const num = typeof val === 'number' ? val : parseInt(val, 10) || val;
204
+ Object.assign(elements.floating.style, { zIndex: num });
205
+ return {};
206
+ },
207
+ }), [dropdownZIndex]);
208
+ const offsetMiddleware = useMemo(() => offset({ mainAxis: 4 }), []);
209
+ const translateProps = useMemo(() => ({
210
+ duration: {
211
+ enter: MOTION_DURATION.moderate,
212
+ exit: MOTION_DURATION.moderate,
213
+ },
214
+ easing: {
215
+ enter: MOTION_EASING.standard,
216
+ exit: MOTION_EASING.standard,
217
+ },
218
+ }), []);
219
+ return (jsxs("div", { ref: ref, className: cx(cascaderClasses.host, fullWidth && cascaderClasses.hostFullWidth), children: [jsx(Popper, { anchor: anchorRef, open: open, disablePortal: !globalPortal, options: {
220
+ placement: 'bottom-start',
221
+ middleware: [offsetMiddleware, zIndexMiddleware],
222
+ }, children: jsx(TransitionGroup, { component: null, children: open && (createElement(Translate, { ...translateProps, from: "bottom", key: "cascader-dropdown", in: true },
223
+ jsx("div", { children: jsx("div", { ref: dropdownRef, className: cascaderClasses.dropdownPanels, children: panels.map((panelOptions, panelIndex) => {
224
+ var _a, _b, _c;
225
+ return (jsx(CascaderPanel, { activeId: (_a = activePath[panelIndex]) === null || _a === void 0 ? void 0 : _a.id, focusedId: panelIndex === panels.length - 1 &&
226
+ keyboardFocusedIndex >= 0
227
+ ? (_b = panels[panelIndex][keyboardFocusedIndex]) === null || _b === void 0 ? void 0 : _b.id
228
+ : undefined, maxHeight: menuMaxHeight, onSelect: (option, isLeaf) => handleItemSelect(panelIndex, option, isLeaf), options: panelOptions, selectedId: value.length > 0 && panelIndex === value.length - 1
229
+ ? (_c = value[panelIndex]) === null || _c === void 0 ? void 0 : _c.id
230
+ : undefined }, panelIndex));
231
+ }) }) }))) }) }), jsx(SelectTrigger, { ref: anchorRef, active: open, className: cx(className, isPartial && cascaderClasses.triggerPartial), disabled: disabled, fullWidth: fullWidth, inputProps: {
232
+ onKeyDown: (e) => {
233
+ if (!open && (e.key === ' ' || e.key === 'Enter')) {
234
+ e.preventDefault();
235
+ handleOpen();
236
+ }
237
+ },
238
+ }, isForceClearable: clearable && !disabled && !readOnly && value.length > 0, mode: "single", onClick: open ? handleClose : handleOpen, onClear: handleClear, placeholder: placeholder, readOnly: readOnly, required: required, size: size, type: error ? 'error' : 'default', value: triggerValue })] }));
239
+ });
240
+
241
+ export { Cascader as default };
@@ -0,0 +1,29 @@
1
+ import { CascaderOption } from './typings';
2
+ export interface CascaderPanelProps {
3
+ /**
4
+ * The id of the currently active (navigating) option.
5
+ */
6
+ activeId?: string;
7
+ /**
8
+ * The id of the keyboard-focused option in this panel.
9
+ */
10
+ focusedId?: string;
11
+ /**
12
+ * The max height for the panel.
13
+ */
14
+ maxHeight?: number | string;
15
+ /**
16
+ * Called when an option is clicked.
17
+ * `isLeaf` is true if the option has no children.
18
+ */
19
+ onSelect: (option: CascaderOption, isLeaf: boolean) => void;
20
+ /**
21
+ * The options to render in this panel.
22
+ */
23
+ options: CascaderOption[];
24
+ /**
25
+ * The id of the confirmed selected option at this level.
26
+ */
27
+ selectedId?: string;
28
+ }
29
+ export default function CascaderPanel({ activeId, focusedId, maxHeight, onSelect, options, selectedId, }: CascaderPanelProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,29 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { cascaderClasses } from '@mezzanine-ui/core/cascader';
4
+ import { CheckedIcon, CaretRightIcon } from '@mezzanine-ui/icons';
5
+ import Icon from '../Icon/Icon.js';
6
+ import cx from 'clsx';
7
+
8
+ function CascaderPanel({ activeId, focusedId, maxHeight, onSelect, options, selectedId, }) {
9
+ const toItemId = (optionId) => `mzn-cascader-option-${optionId}`;
10
+ return (jsx("div", { className: cascaderClasses.panel, style: maxHeight ? { maxHeight } : undefined, children: jsx("ul", { "aria-activedescendant": focusedId ? toItemId(focusedId) : undefined, "aria-label": "Options", role: "listbox", style: { listStyle: 'none', margin: 0, padding: 0 }, tabIndex: -1, children: options.map((option) => {
11
+ const isLeaf = !option.children || option.children.length === 0;
12
+ const isActive = option.id === activeId;
13
+ const isSelected = option.id === selectedId;
14
+ return (jsxs("li", { "aria-disabled": option.disabled || undefined, "aria-expanded": !isLeaf ? isActive : undefined, "aria-selected": isSelected, className: cx(cascaderClasses.item, isActive && cascaderClasses.itemActive, option.disabled && cascaderClasses.itemDisabled, option.id === focusedId && cascaderClasses.itemFocused, isSelected && cascaderClasses.itemSelected), id: toItemId(option.id), onClick: () => {
15
+ if (!option.disabled) {
16
+ onSelect(option, isLeaf);
17
+ }
18
+ }, onKeyDown: (e) => {
19
+ if (e.key === 'Enter' || e.key === ' ') {
20
+ e.preventDefault();
21
+ if (!option.disabled) {
22
+ onSelect(option, isLeaf);
23
+ }
24
+ }
25
+ }, role: "option", children: [jsx("span", { className: cascaderClasses.itemLabel, children: option.name }), jsx("span", { className: cascaderClasses.itemAppend, children: isLeaf ? (isSelected && jsx(Icon, { icon: CheckedIcon })) : (jsx(Icon, { icon: CaretRightIcon })) })] }, option.id));
26
+ }) }) }));
27
+ }
28
+
29
+ export { CascaderPanel as default };
@@ -0,0 +1,5 @@
1
+ export { default } from './Cascader';
2
+ export type { CascaderProps } from './typings';
3
+ export type { CascaderOption, CascaderSize } from './typings';
4
+ export { default as CascaderPanel } from './CascaderPanel';
5
+ export type { CascaderPanelProps } from './CascaderPanel';
@@ -0,0 +1,2 @@
1
+ export { default } from './Cascader.js';
2
+ export { default as CascaderPanel } from './CascaderPanel.js';
@@ -0,0 +1,92 @@
1
+ import { CascaderSize } from '@mezzanine-ui/core/cascader';
2
+ export type { CascaderSize };
3
+ export interface CascaderOption {
4
+ children?: CascaderOption[];
5
+ disabled?: boolean;
6
+ id: string;
7
+ name: string;
8
+ }
9
+ export interface CascaderBaseProps {
10
+ /**
11
+ * Additional class name.
12
+ */
13
+ className?: string;
14
+ /**
15
+ * Whether to show the clear button when a value is selected.
16
+ * @default false
17
+ */
18
+ clearable?: boolean;
19
+ /**
20
+ * Whether the cascader is disabled.
21
+ * @default false
22
+ */
23
+ disabled?: boolean;
24
+ /**
25
+ * Whether to show in error state.
26
+ * @default false
27
+ */
28
+ error?: boolean;
29
+ /**
30
+ * Whether the cascader takes full width.
31
+ * @default false
32
+ */
33
+ fullWidth?: boolean;
34
+ /**
35
+ * The z-index of the dropdown.
36
+ */
37
+ dropdownZIndex?: number | string;
38
+ /**
39
+ * Whether to enable portal for the dropdown.
40
+ * @default true
41
+ */
42
+ globalPortal?: boolean;
43
+ /**
44
+ * The max height of each cascader panel column.
45
+ */
46
+ menuMaxHeight?: number | string;
47
+ /**
48
+ * Callback fired when the dropdown is closed.
49
+ */
50
+ onBlur?: () => void;
51
+ /**
52
+ * Callback fired when the dropdown is opened.
53
+ */
54
+ onFocus?: () => void;
55
+ /**
56
+ * The tree options for the cascader.
57
+ */
58
+ options: CascaderOption[];
59
+ /**
60
+ * Placeholder text for the trigger input.
61
+ */
62
+ placeholder?: string;
63
+ /**
64
+ * Whether the cascader is read-only.
65
+ * @default false
66
+ */
67
+ readOnly?: boolean;
68
+ /**
69
+ * Whether the cascader is required.
70
+ * @default false
71
+ */
72
+ required?: boolean;
73
+ /**
74
+ * The size of the trigger input.
75
+ * @default 'main'
76
+ */
77
+ size?: CascaderSize;
78
+ }
79
+ export interface CascaderProps extends CascaderBaseProps {
80
+ /**
81
+ * Uncontrolled default value (array from root to leaf).
82
+ */
83
+ defaultValue?: CascaderOption[];
84
+ /**
85
+ * Callback fired when the final leaf option is selected.
86
+ */
87
+ onChange?: (value: CascaderOption[]) => void;
88
+ /**
89
+ * Controlled value (array from root to leaf).
90
+ */
91
+ value?: CascaderOption[];
92
+ }
@@ -1,5 +1,5 @@
1
1
  import { ReactElement } from 'react';
2
- import { DescriptionOrientation } from '@mezzanine-ui/core/description';
2
+ import { DescriptionOrientation, DescriptionSize } from '@mezzanine-ui/core/description';
3
3
  import { DescriptionTitleProps } from './DescriptionTitle';
4
4
  import { DescriptionContentProps } from './DescriptionContent';
5
5
  import { BadgeProps } from '../Badge/typings';
@@ -21,6 +21,11 @@ export type DescriptionProps = DistributiveOmit<DescriptionTitleProps, 'classNam
21
21
  * @default 'horizontal'
22
22
  */
23
23
  orientation?: DescriptionOrientation;
24
+ /**
25
+ * Controls the text size of the description content
26
+ * @default 'main'
27
+ */
28
+ size?: DescriptionSize;
24
29
  /**
25
30
  * title text for description
26
31
  */
@@ -1,13 +1,20 @@
1
1
  'use client';
2
- import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { forwardRef } from 'react';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { forwardRef, isValidElement, cloneElement } from 'react';
4
4
  import { descriptionClasses } from '@mezzanine-ui/core/description';
5
5
  import DescriptionTitle from './DescriptionTitle.js';
6
+ import { DescriptionContext } from './DescriptionContext.js';
6
7
  import cx from 'clsx';
7
8
 
8
9
  const Description = forwardRef(function Description(props, ref) {
9
- const { children, className, orientation = 'horizontal', title, ...rest } = props;
10
- return (jsxs("div", { className: cx(descriptionClasses.host, descriptionClasses.orientation(orientation), className), ref: ref, children: [jsx(DescriptionTitle, { ...rest, children: title }), children] }));
10
+ var _a;
11
+ const { children, className, orientation = 'horizontal', size = 'main', title, ...rest } = props;
12
+ const injectedChildren = isValidElement(children)
13
+ ? cloneElement(children, {
14
+ size: (_a = children.props.size) !== null && _a !== void 0 ? _a : size,
15
+ })
16
+ : children;
17
+ return (jsx(DescriptionContext.Provider, { value: { size }, children: jsxs("div", { className: cx(descriptionClasses.host, descriptionClasses.orientation(orientation), className), ref: ref, children: [jsx(DescriptionTitle, { ...rest, children: title }), injectedChildren] }) }));
11
18
  });
12
19
 
13
20
  export { Description as default };
@@ -1,5 +1,5 @@
1
1
  import { IconDefinition } from '@mezzanine-ui/icons';
2
- import { DescriptionSize, DescriptionContentVariant } from '@mezzanine-ui/core/description';
2
+ import { DescriptionContentVariant, DescriptionSize } from '@mezzanine-ui/core/description';
3
3
  interface DescriptionContentBaseProps {
4
4
  /**
5
5
  * Custom class name for content
@@ -10,8 +10,9 @@ interface DescriptionContentBaseProps {
10
10
  */
11
11
  children: string;
12
12
  /**
13
- * Control the text size of the content
14
- * @default 'main'
13
+ * Controls the text size of the content. When provided, overrides the size
14
+ * inherited from a parent <Description> component.
15
+ * @default context value or 'main'
15
16
  */
16
17
  size?: DescriptionSize;
17
18
  /**
@@ -31,6 +32,11 @@ interface DescriptionContentBaseProps {
31
32
  interface DescriptionContentWithClickableIcon {
32
33
  className?: string;
33
34
  children: string;
35
+ /**
36
+ * Controls the text size of the content. When provided, overrides the size
37
+ * inherited from a parent <Description> component.
38
+ * @default context value or 'main'
39
+ */
34
40
  size?: DescriptionSize;
35
41
  variant: Extract<DescriptionContentVariant, 'with-icon'>;
36
42
  icon: IconDefinition;
@@ -3,11 +3,14 @@ import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { forwardRef } from 'react';
4
4
  import { CaretUpIcon, CaretDownIcon } from '@mezzanine-ui/icons';
5
5
  import { descriptionClasses } from '@mezzanine-ui/core/description';
6
+ import { useDescriptionContext } from './DescriptionContext.js';
6
7
  import Icon from '../Icon/Icon.js';
7
8
  import cx from 'clsx';
8
9
 
9
10
  const DescriptionContent = forwardRef(function DescriptionContent(props, ref) {
10
- const { className, children, icon, onClickIcon, size = 'main', variant = 'normal', } = props;
11
+ const { className, children, icon, onClickIcon, size: sizeProp, variant = 'normal', } = props;
12
+ const { size: contextSize } = useDescriptionContext();
13
+ const size = sizeProp !== null && sizeProp !== void 0 ? sizeProp : contextSize;
11
14
  return (jsxs("span", { className: cx(descriptionClasses.contentHost, descriptionClasses.contentVariant(variant), descriptionClasses.contentSize(size), className), ref: ref, children: [variant === 'trend-up' && (jsx(Icon, { className: descriptionClasses.contentTrendUp, icon: CaretUpIcon, size: 16 })), variant === 'trend-down' && (jsx(Icon, { className: descriptionClasses.contentTrendDown, icon: CaretDownIcon, size: 16 })), children, variant === 'with-icon' && icon && (jsx(Icon, { className: descriptionClasses.contentIcon, icon: icon, size: 16, onClick: onClickIcon }))] }));
12
15
  });
13
16
 
@@ -0,0 +1,6 @@
1
+ import { DescriptionSize } from '@mezzanine-ui/core/description';
2
+ export interface DescriptionContextValue {
3
+ size: DescriptionSize;
4
+ }
5
+ export declare const DescriptionContext: import("react").Context<DescriptionContextValue>;
6
+ export declare const useDescriptionContext: () => DescriptionContextValue;