@mezzanine-ui/react 1.0.0-rc.2 → 1.0.0-rc.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.
@@ -1,5 +1,10 @@
1
1
  import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
2
2
  export interface AccordionGroupProps extends NativeElementPropsWithoutKeyAndRef<'div'> {
3
+ /**
4
+ * If true, only one accordion can be expanded at a time.
5
+ * @default false
6
+ */
7
+ exclusive?: boolean;
3
8
  /**
4
9
  * The size of accordion group, which will be passed to each Accordion in the group.
5
10
  * @default 'main'
@@ -1,26 +1,49 @@
1
1
  'use client';
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { forwardRef, useMemo, isValidElement } from 'react';
3
+ import { forwardRef, useState, useMemo, isValidElement, useCallback, cloneElement } from 'react';
4
4
  import { accordionGroupClasses } from '@mezzanine-ui/core/accordion';
5
5
  import { flattenChildren } from '../utils/flatten-children.js';
6
6
  import Accordion from './Accordion.js';
7
7
  import cx from 'clsx';
8
8
 
9
9
  const AccordionGroup = forwardRef(function AccordionGroup(props, ref) {
10
- const { className, children, size, ...rest } = props;
11
- const childrenWithSize = useMemo(() => flattenChildren(children).map((child) => {
10
+ const { className, children, exclusive = false, size, ...rest } = props;
11
+ const [expandedIndex, setExpandedIndex] = useState(null);
12
+ const flattenedChildren = useMemo(() => flattenChildren(children), [children]);
13
+ const defaultExpandedIndex = useMemo(() => flattenedChildren.findIndex((child) => isValidElement(child) &&
14
+ child.type === Accordion &&
15
+ typeof child.props.expanded === 'undefined' &&
16
+ !!child.props.defaultExpanded), [flattenedChildren]);
17
+ const resolvedExpandedIndex = expandedIndex === null ? defaultExpandedIndex : expandedIndex;
18
+ const handleChange = useCallback((index, open) => {
19
+ setExpandedIndex(open ? index : -1);
20
+ }, []);
21
+ const childrenWithProps = useMemo(() => flattenedChildren.map((child, index) => {
12
22
  if (isValidElement(child) && child.type === Accordion) {
13
- return {
14
- ...child,
15
- props: {
16
- ...child.props,
17
- size,
18
- },
19
- };
23
+ const accordionProps = child.props;
24
+ const extraProps = { size };
25
+ if (exclusive) {
26
+ const isExpandedControlled = typeof accordionProps.expanded !== 'undefined';
27
+ if (!isExpandedControlled) {
28
+ extraProps.expanded = resolvedExpandedIndex === index;
29
+ }
30
+ extraProps.onChange = (open) => {
31
+ if (typeof accordionProps.onChange === 'function') {
32
+ accordionProps.onChange(open);
33
+ }
34
+ if (!isExpandedControlled) {
35
+ handleChange(index, open);
36
+ }
37
+ };
38
+ }
39
+ return cloneElement(child, {
40
+ ...accordionProps,
41
+ ...extraProps,
42
+ });
20
43
  }
21
44
  return child;
22
- }), [children, size]);
23
- return (jsx("div", { ...rest, ref: ref, className: cx(accordionGroupClasses.host, className), children: childrenWithSize }));
45
+ }), [exclusive, flattenedChildren, handleChange, resolvedExpandedIndex, size]);
46
+ return (jsx("div", { ...rest, ref: ref, className: cx(accordionGroupClasses.host, className), children: childrenWithProps }));
24
47
  });
25
48
 
26
49
  export { AccordionGroup as default };
@@ -131,6 +131,7 @@ export interface AutoCompleteBaseProps extends Omit<SelectTriggerProps, 'active'
131
131
  * Imperative handle to control search text externally (e.g. reset or sync).
132
132
  */
133
133
  searchTextControlRef?: RefObject<{
134
+ reset: () => void;
134
135
  setSearchText: Dispatch<SetStateAction<string>>;
135
136
  } | undefined>;
136
137
  /**
@@ -92,7 +92,10 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
92
92
  : undefined,
93
93
  });
94
94
  /** export set search text action to props (allow user to customize search text) */
95
- useImperativeHandle(searchTextControlRef, () => ({ setSearchText }));
95
+ useImperativeHandle(searchTextControlRef, () => ({
96
+ reset: resetSearchInputsAndOptions,
97
+ setSearchText,
98
+ }));
96
99
  /** Track created items (new, unselected, all) */
97
100
  const { clearUnselected, filterUnselected, isCreated, markCreated, clearNewlyCreated, markUnselected, } = useCreationTracker();
98
101
  const creationEnabled = addable && typeof onInsert === 'function';
@@ -152,7 +152,7 @@ const DatePicker = forwardRef(function DatePicker(props, ref) {
152
152
  onCalendarToggle(!open);
153
153
  };
154
154
  const suffixActionIcon = (jsx(Icon, { "aria-label": "Open calendar", icon: CalendarIcon, onClick: readOnly ? undefined : onIconClick }));
155
- return (jsxs(Fragment, { children: [jsx(PickerTrigger, { ...restTriggerProps, ref: triggerComposedRef, className: className, clearable: clearable, disabled: disabled, error: error, errorMessages: errorMessages, format: format, fullWidth: fullWidth, inputProps: resolvedInputProps, inputRef: inputRef, onChange: (e) => {
155
+ return (jsxs(Fragment, { children: [jsx(PickerTrigger, { ...restTriggerProps, ref: triggerComposedRef, className: className, clearable: clearable, disabled: disabled, error: error, forceShowClearable: !!internalValue, hideSuffixWhenClearable: clearable, errorMessages: errorMessages, format: format, fullWidth: fullWidth, inputProps: resolvedInputProps, inputRef: inputRef, onChange: (e) => {
156
156
  onInputChange(e);
157
157
  onCalendarChange(e.target.value);
158
158
  onCalendarToggle(true);
@@ -223,7 +223,7 @@ const DateRangePicker = forwardRef(function DateRangePicker(props, ref) {
223
223
  onCalendarToggle(!open);
224
224
  }, [onChange, onCalendarToggle, open, valueProp]);
225
225
  const suffixActionIcon = jsx(Icon, { icon: CalendarIcon, onClick: onIconClick });
226
- return (jsxs(Fragment, { children: [jsx(RangePickerTrigger, { className: className, clearable: clearable, disabled: disabled, error: error, errorMessagesFrom: errorMessagesFrom, errorMessagesTo: errorMessagesTo, format: format, fullWidth: fullWidth, inputFromPlaceholder: inputFromPlaceholder, inputFromProps: inputFromProps, inputFromRef: inputFromRef, inputFromValue: inputFromValue, inputToPlaceholder: inputToPlaceholder, inputToProps: inputToProps, inputToRef: inputToRef, inputToValue: inputToValue, onClear: onClear, onFromBlur: onFromBlur, onFromFocus: onFromFocusHandler, onInputFromChange: onInputFromChange, onInputToChange: onInputToChange, onToBlur: onToBlur, onToFocus: onToFocusHandler, prefix: prefix, readOnly: readOnly, ref: triggerComposedRef, required: required, size: size, suffixActionIcon: suffixActionIcon, validateFrom: validateFrom, validateTo: validateTo }), jsx(DateRangePickerCalendar, { actions: actions, anchor: anchorRef, calendarProps: calendarProps, disabledMonthSwitch: disabledMonthSwitch, disabledYearSwitch: disabledYearSwitch, disableOnDoubleNext: disableOnDoubleNext, disableOnDoublePrev: disableOnDoublePrev, disableOnNext: disableOnNext, disableOnPrev: disableOnPrev, displayMonthLocale: displayMonthLocale, displayWeekDayLocale: displayWeekDayLocale, fadeProps: fadeProps, firstCalendarRef: firstCalendarRef, isDateDisabled: isDateDisabled, isDateInRange: getIsInRangeHandler('date'), isHalfYearDisabled: isHalfYearDisabled, isHalfYearInRange: getIsInRangeHandler('half-year'), isMonthDisabled: isMonthDisabled, isMonthInRange: getIsInRangeHandler('month'), isQuarterDisabled: isQuarterDisabled, isQuarterInRange: getIsInRangeHandler('quarter'), isWeekDisabled: isWeekDisabled, isWeekInRange: getIsInRangeHandler('week'), isYearDisabled: isYearDisabled, isYearInRange: getIsInRangeHandler('year'), mode: mode, onChange: onCalendarChangeWithCloseControl, onDateHover: onCalendarHover, onHalfYearHover: onCalendarHover, onMonthHover: onCalendarHover, onQuarterHover: onCalendarHover, onWeekHover: onCalendarHover, onYearHover: onCalendarHover, open: open, popperProps: popperProps, quickSelect: quickSelect, ref: calendarRef, referenceDate: referenceDate, renderAnnotations: renderAnnotations, secondCalendarRef: secondCalendarRef, value: calendarValue })] }));
226
+ return (jsxs(Fragment, { children: [jsx(RangePickerTrigger, { className: className, clearable: clearable, disabled: disabled, forceShowClearable: !!(internalValue[0] || internalValue[1]), hideSuffixWhenClearable: clearable, error: error, errorMessagesFrom: errorMessagesFrom, errorMessagesTo: errorMessagesTo, format: format, fullWidth: fullWidth, inputFromPlaceholder: inputFromPlaceholder, inputFromProps: inputFromProps, inputFromRef: inputFromRef, inputFromValue: inputFromValue, inputToPlaceholder: inputToPlaceholder, inputToProps: inputToProps, inputToRef: inputToRef, inputToValue: inputToValue, onClear: onClear, onFromBlur: onFromBlur, onFromFocus: onFromFocusHandler, onInputFromChange: onInputFromChange, onInputToChange: onInputToChange, onToBlur: onToBlur, onToFocus: onToFocusHandler, prefix: prefix, readOnly: readOnly, ref: triggerComposedRef, required: required, size: size, suffixActionIcon: suffixActionIcon, validateFrom: validateFrom, validateTo: validateTo }), jsx(DateRangePickerCalendar, { actions: actions, anchor: anchorRef, calendarProps: calendarProps, disabledMonthSwitch: disabledMonthSwitch, disabledYearSwitch: disabledYearSwitch, disableOnDoubleNext: disableOnDoubleNext, disableOnDoublePrev: disableOnDoublePrev, disableOnNext: disableOnNext, disableOnPrev: disableOnPrev, displayMonthLocale: displayMonthLocale, displayWeekDayLocale: displayWeekDayLocale, fadeProps: fadeProps, firstCalendarRef: firstCalendarRef, isDateDisabled: isDateDisabled, isDateInRange: getIsInRangeHandler('date'), isHalfYearDisabled: isHalfYearDisabled, isHalfYearInRange: getIsInRangeHandler('half-year'), isMonthDisabled: isMonthDisabled, isMonthInRange: getIsInRangeHandler('month'), isQuarterDisabled: isQuarterDisabled, isQuarterInRange: getIsInRangeHandler('quarter'), isWeekDisabled: isWeekDisabled, isWeekInRange: getIsInRangeHandler('week'), isYearDisabled: isYearDisabled, isYearInRange: getIsInRangeHandler('year'), mode: mode, onChange: onCalendarChangeWithCloseControl, onDateHover: onCalendarHover, onHalfYearHover: onCalendarHover, onMonthHover: onCalendarHover, onQuarterHover: onCalendarHover, onWeekHover: onCalendarHover, onYearHover: onCalendarHover, open: open, popperProps: popperProps, quickSelect: quickSelect, ref: calendarRef, referenceDate: referenceDate, renderAnnotations: renderAnnotations, secondCalendarRef: secondCalendarRef, value: calendarValue })] }));
227
227
  });
228
228
 
229
229
  export { DateRangePicker as default };
@@ -217,7 +217,7 @@ const DateTimePicker = forwardRef(function DateTimePicker(props, ref) {
217
217
  }
218
218
  }, [disabled, focusedInput, onPanelToggle, readOnly]);
219
219
  const suffix = (jsx(Icon, { "aria-label": "Open calendar", icon: CalendarTimeIcon, onClick: onCalendarIconClick }));
220
- return (jsxs(Fragment, { children: [jsx(PickerTriggerWithSeparator, { ...restTriggerProps, ref: triggerComposedRef, className: className, clearable: clearable, disabled: disabled, error: error, formatLeft: formatDate, formatRight: formatTime, fullWidth: fullWidth, inputLeftRef: inputLeftRef, inputRightRef: inputRightRef, onBlurLeft: () => { }, onBlurRight: () => { }, onChangeLeft: onChangeLeft, onChangeRight: onChangeRight, onClear: onClear, onFocusLeft: onFocusLeft, onFocusRight: onFocusRight, onLeftComplete: onLeftComplete, onPasteIsoValueLeft: onPasteIsoValueLeft, onPasteIsoValueRight: onPasteIsoValueRight, onRightComplete: onRightComplete, placeholderLeft: placeholderLeft, placeholderRight: placeholderRight, prefix: prefix, readOnly: readOnly, required: required, size: size, suffix: suffix, valueLeft: displayDateValue, valueRight: displayTimeValue }), jsx(DatePickerCalendar, { ref: calendarPanelRef, anchor: anchorRef, calendarProps: calendarProps, calendarRef: calendarRef, disabledMonthSwitch: disabledMonthSwitch, disableOnDoubleNext: disableOnDoubleNext, disableOnDoublePrev: disableOnDoublePrev, disableOnNext: disableOnNext, disableOnPrev: disableOnPrev, disabledYearSwitch: disabledYearSwitch, displayMonthLocale: displayMonthLocale, fadeProps: fadeProps, isDateDisabled: isDateDisabled, isHalfYearDisabled: isHalfYearDisabled, isMonthDisabled: isMonthDisabled, isQuarterDisabled: isQuarterDisabled, isWeekDisabled: isWeekDisabled, isYearDisabled: isYearDisabled, mode: mode, onChange: onCalendarChange, open: openCalendar, popperProps: popperProps, referenceDate: referenceDate, value: dateValue }), jsx(TimePickerPanel, { ref: timePanelRef, anchor: anchorRef, fadeProps: fadeProps, hideHour: hideHour, hideMinute: hideMinute, hideSecond: hideSecond, hourStep: hourStep, minuteStep: minuteStep, onChange: onTimePanelChange, open: openTimePanel, popperProps: popperPropsTime, secondStep: secondStep, value: timeValue })] }));
220
+ return (jsxs(Fragment, { children: [jsx(PickerTriggerWithSeparator, { ...restTriggerProps, ref: triggerComposedRef, className: className, clearable: clearable, disabled: disabled, forceShowClearable: !!(dateValue || timeValue), hideSuffixWhenClearable: clearable, error: error, formatLeft: formatDate, formatRight: formatTime, fullWidth: fullWidth, inputLeftRef: inputLeftRef, inputRightRef: inputRightRef, onBlurLeft: () => { }, onBlurRight: () => { }, onChangeLeft: onChangeLeft, onChangeRight: onChangeRight, onClear: onClear, onFocusLeft: onFocusLeft, onFocusRight: onFocusRight, onLeftComplete: onLeftComplete, onPasteIsoValueLeft: onPasteIsoValueLeft, onPasteIsoValueRight: onPasteIsoValueRight, onRightComplete: onRightComplete, placeholderLeft: placeholderLeft, placeholderRight: placeholderRight, prefix: prefix, readOnly: readOnly, required: required, size: size, suffix: suffix, valueLeft: displayDateValue, valueRight: displayTimeValue }), jsx(DatePickerCalendar, { ref: calendarPanelRef, anchor: anchorRef, calendarProps: calendarProps, calendarRef: calendarRef, disabledMonthSwitch: disabledMonthSwitch, disableOnDoubleNext: disableOnDoubleNext, disableOnDoublePrev: disableOnDoublePrev, disableOnNext: disableOnNext, disableOnPrev: disableOnPrev, disabledYearSwitch: disabledYearSwitch, displayMonthLocale: displayMonthLocale, fadeProps: fadeProps, isDateDisabled: isDateDisabled, isHalfYearDisabled: isHalfYearDisabled, isMonthDisabled: isMonthDisabled, isQuarterDisabled: isQuarterDisabled, isWeekDisabled: isWeekDisabled, isYearDisabled: isYearDisabled, mode: mode, onChange: onCalendarChange, open: openCalendar, popperProps: popperProps, referenceDate: referenceDate, value: dateValue }), jsx(TimePickerPanel, { ref: timePanelRef, anchor: anchorRef, fadeProps: fadeProps, hideHour: hideHour, hideMinute: hideMinute, hideSecond: hideSecond, hourStep: hourStep, minuteStep: minuteStep, onChange: onTimePanelChange, open: openTimePanel, popperProps: popperPropsTime, secondStep: secondStep, value: timeValue })] }));
221
221
  });
222
222
 
223
223
  export { DateTimePicker as default };
@@ -320,8 +320,11 @@ function DropdownItem(props) {
320
320
  return renderDefaultOptions(optionList, startIndex);
321
321
  };
322
322
  const { elements: renderedOptions } = renderOptions(optionsContent, 0, -1);
323
- // Show full status when options are empty and status is provided, but not when loadingPosition is 'bottom'
324
- const shouldShowFullStatus = optionsContent.length === 0 && status && loadingPosition !== 'bottom';
323
+ // Show full status when options are empty and status is provided.
324
+ // Empty status always shows as full; loading status respects loadingPosition (bottom vs full).
325
+ const shouldShowFullStatus = optionsContent.length === 0 &&
326
+ status &&
327
+ (status === 'empty' || loadingPosition !== 'bottom');
325
328
  // Show bottom loading when status is loading and loadingPosition is bottom
326
329
  const shouldShowBottomLoading = status === 'loading' && loadingPosition === 'bottom';
327
330
  const listStyle = useMemo(() => {
@@ -20,6 +20,12 @@ export interface NavigationProps extends Omit<NativeElementPropsWithoutKeyAndRef
20
20
  * @default false (expanded)
21
21
  */
22
22
  collapsed?: boolean;
23
+ /**
24
+ * When true, href must match the current pathname exactly to be activated.
25
+ * When false (default), any href that is a prefix of the current pathname will be activated.
26
+ * @default false
27
+ */
28
+ exactActivatedMatch?: boolean;
23
29
  /**
24
30
  * Whether to show search input
25
31
  */
@@ -15,7 +15,7 @@ import Input from '../Input/Input.js';
15
15
  import cx from 'clsx';
16
16
 
17
17
  const Navigation = forwardRef((props, ref) => {
18
- const { activatedPath, children = [], className, collapsed: collapsedProp, filter, onCollapseChange, onOptionClick, optionsAnchorComponent, ...rest } = props;
18
+ const { activatedPath, children = [], className, collapsed: collapsedProp, exactActivatedMatch = false, filter, onCollapseChange, onOptionClick, optionsAnchorComponent, ...rest } = props;
19
19
  const [collapsedState, setCollapsedState] = useState(collapsedProp || false);
20
20
  const collapsed = collapsedProp !== null && collapsedProp !== void 0 ? collapsedProp : collapsedState;
21
21
  const handleCollapseChange = useCallback((newCollapsed) => {
@@ -83,7 +83,11 @@ const Navigation = forwardRef((props, ref) => {
83
83
  continue;
84
84
  }
85
85
  const newPath = [...path, newKey];
86
- if (item.props.href && item.props.href === currentPathname) {
86
+ const hrefMatches = exactActivatedMatch
87
+ ? item.props.href === currentPathname
88
+ : currentPathname === item.props.href ||
89
+ currentPathname.startsWith(item.props.href + '/');
90
+ if (item.props.href && hrefMatches) {
87
91
  combineSetActivatedPath(newPath);
88
92
  return true;
89
93
  }
@@ -98,7 +102,7 @@ const Navigation = forwardRef((props, ref) => {
98
102
  };
99
103
  checkActivatedPathKey(level1Items, []);
100
104
  hrefActivated.current = true;
101
- }, [combineSetActivatedPath, currentPathname, level1Items]);
105
+ }, [combineSetActivatedPath, currentPathname, exactActivatedMatch, level1Items]);
102
106
  const { contentRef, visibleCount } = useVisibleItems(items, collapsed);
103
107
  const { collapsedItems, collapsedMenuItems } = useMemo(() => {
104
108
  return {
@@ -60,7 +60,7 @@ function SelectTriggerComponent(props) {
60
60
  return (jsxs(TextField, { ref: innerRef, ...interactiveProps, ...sanitizedTextFieldProps, onClick: onClick, active: active, className: cx(selectClasses.trigger, selectClasses.triggerMode(mode), selectClasses.triggerSelected(Array.isArray(props.value) ? (_a = props.value) === null || _a === void 0 ? void 0 : _a.length : props.value), {
61
61
  [selectClasses.triggerReadOnly]: readOnly,
62
62
  [selectClasses.triggerDisabled]: disabled,
63
- }, className), error: type === 'error', forceShowClearable: shouldEnableClearable, size: size, suffix: forceHideSuffixActionIcon ? undefined : suffixActionIcon, clearable: shouldEnableClearable, children: [jsx("input", { ...inputProps, ref: inputRef, "aria-autocomplete": "list", "aria-haspopup": "listbox", autoComplete: "off", className: cx(selectClasses.triggerInput, inputProps === null || inputProps === void 0 ? void 0 : inputProps.className), disabled: disabled, placeholder: placeholder, readOnly: (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.readOnly) !== null && _b !== void 0 ? _b : true, required: required, type: "text", value: renderValue() }), isMultipleSelection(props) && ((_c = props.value) === null || _c === void 0 ? void 0 : _c.length)
63
+ }, className), error: type === 'error', clearable: shouldEnableClearable, forceShowClearable: shouldEnableClearable, size: size, suffix: forceHideSuffixActionIcon ? undefined : suffixActionIcon, children: [jsx("input", { ...inputProps, ref: inputRef, "aria-autocomplete": "list", "aria-haspopup": "listbox", autoComplete: "off", className: cx(selectClasses.triggerInput, inputProps === null || inputProps === void 0 ? void 0 : inputProps.className), disabled: disabled, placeholder: placeholder, readOnly: (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.readOnly) !== null && _b !== void 0 ? _b : true, required: required, type: "text", value: renderValue() }), isMultipleSelection(props) && ((_c = props.value) === null || _c === void 0 ? void 0 : _c.length)
64
64
  ? (jsx(SelectTriggerTags, { disabled: disabled, overflowStrategy: overflowStrategy, inputProps: inputProps, inputRef: inputRef, onTagClose: onTagClose, readOnly: readOnly, required: required, searchText: searchText, size: size, showTextInputAfterTags: showTextInputAfterTags, value: props.value }))
65
65
  : null] }));
66
66
  }
package/Table/Table.js CHANGED
@@ -23,7 +23,7 @@ import Scrollbar from '../Scrollbar/Scrollbar.js';
23
23
  import cx from 'clsx';
24
24
 
25
25
  function TableInner(props, ref) {
26
- const { actions, className, columns, dataSource, draggable, emptyProps, expandable, fullWidth = false, highlight = 'row', loading = false, loadingRowsCount = 10, minHeight, nested = false, pagination, pinnable, resizable = false, rowHeightPreset = 'base', rowSelection, scroll, showHeader = true, size = 'main', sticky = true, style, toggleable, collectable, transitionState, zebraStriping, separatorAtRowIndexes, ...restProps } = props;
26
+ const { actions, className, columns, dataSource, draggable, emptyProps, expandable, fullWidth = false, highlight = 'row', loading = false, loadingRowsCount = 10, minHeight, nested = false, pagination, pinnable, resizable = false, rowState, rowHeightPreset = 'base', rowSelection, scroll, showHeader = true, size = 'main', sticky = true, style, toggleable, collectable, transitionState, zebraStriping, separatorAtRowIndexes, ...restProps } = props;
27
27
  const hostRef = useRef(null);
28
28
  const composedHostRef = useComposeRefs([ref, hostRef]);
29
29
  /** Feature: Loading */
@@ -244,6 +244,7 @@ function TableInner(props, ref) {
244
244
  pagination: pagination || undefined,
245
245
  pinnable: pinnableState,
246
246
  resizable,
247
+ rowState,
247
248
  rowHeight,
248
249
  scroll,
249
250
  scrollContainerRef,
@@ -272,6 +273,7 @@ function TableInner(props, ref) {
272
273
  pagination,
273
274
  pinnableState,
274
275
  resizable,
276
+ rowState,
275
277
  rowHeight,
276
278
  scroll,
277
279
  scrollContainerRef,
@@ -1,4 +1,4 @@
1
- import type { HighlightMode, TableSize, TableActionsBase, TableColumn, TableDataSource, TableExpandable, TableRowSelection, TableScroll, TableSelectionMode, TableCollectable, TableToggleable, TablePinnable, TableDraggable } from '@mezzanine-ui/core/table';
1
+ import type { HighlightMode, TableSize, TableActionsBase, TableColumn, TableDataSource, TableExpandable, TableRowSelection, TableRowState, TableScroll, TableSelectionMode, TableCollectable, TableToggleable, TablePinnable, TableDraggable } from '@mezzanine-ui/core/table';
2
2
  import type { EmptyProps } from '../Empty';
3
3
  import type { PaginationProps } from '../Pagination';
4
4
  import type { UseTableFixedOffsetsReturn } from './hooks/useTableFixedOffsets';
@@ -59,6 +59,7 @@ export interface TableContextValue<T extends TableDataSource = TableDataSource>
59
59
  pagination?: PaginationProps;
60
60
  pinnable?: TablePinnable;
61
61
  resizable?: boolean;
62
+ rowState?: TableRowState | ((rowData: TableDataSource) => TableRowState | undefined);
62
63
  rowHeight: number;
63
64
  scroll?: TableScroll;
64
65
  scrollContainerRef?: React.RefObject<HTMLDivElement | null>;
@@ -14,6 +14,18 @@ import { TableToggleableCell } from './TableToggleableCell.js';
14
14
  import { composeRefs } from '../../utils/composeRefs.js';
15
15
  import cx from 'clsx';
16
16
 
17
+ const resolveRowStateClass = (state) => {
18
+ switch (state) {
19
+ case 'added':
20
+ return tableClasses.bodyRowStateAdded;
21
+ case 'deleted':
22
+ return tableClasses.bodyRowStateDeleted;
23
+ case 'disabled':
24
+ return tableClasses.bodyRowStateDisabled;
25
+ default:
26
+ return undefined;
27
+ }
28
+ };
17
29
  const parseFixed = (fixed) => {
18
30
  if (fixed === true || fixed === 'start')
19
31
  return 'start';
@@ -24,7 +36,7 @@ const parseFixed = (fixed) => {
24
36
  const TableRowInner = forwardRef(function TableRow(props, ref) {
25
37
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
26
38
  const { className, draggableProvided, record, rowIndex, style } = props;
27
- const { actions, collectable, draggable, expansion, fixedOffsets, highlight, pinnable, rowHeight, selection, separatorAtRowIndexes, toggleable, transitionState, zebraStriping, } = useTableContext();
39
+ const { actions, collectable, draggable, expansion, fixedOffsets, highlight, pinnable, rowState, rowHeight, selection, separatorAtRowIndexes, toggleable, transitionState, zebraStriping, } = useTableContext();
28
40
  const { columns } = useTableDataContext();
29
41
  const isDragging = useMemo(() => {
30
42
  var _a;
@@ -178,7 +190,7 @@ const TableRowInner = forwardRef(function TableRow(props, ref) {
178
190
  [tableClasses.bodyRowSelected]: isSelected,
179
191
  [tableClasses.bodyRowSeparator]: isSeparatorRow,
180
192
  [tableClasses.bodyRowZebra]: isZebraRow,
181
- }, className), "data-index": rowIndex, "data-row-key": rowKey, onMouseLeave: handleMouseLeave, ref: rowRef, tabIndex: 0, ...draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.draggableProps, style: resolvedStyle, children: [renderExpandCell(), renderDragOrPinHandleCell(), renderSelectionCell(), renderCells()] }));
193
+ }, resolveRowStateClass(typeof rowState === 'function' ? rowState(record) : rowState), className), "data-index": rowIndex, "data-row-key": rowKey, onMouseLeave: handleMouseLeave, ref: rowRef, tabIndex: 0, ...draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.draggableProps, style: resolvedStyle, children: [renderExpandCell(), renderDragOrPinHandleCell(), renderSelectionCell(), renderCells()] }));
182
194
  });
183
195
  const TableRow = memo(TableRowInner);
184
196
 
package/Table/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { TABLE_ACTIONS_KEY, tableClasses as classes, getCellAlignClass, getRowKey, type ColumnAlign, type FixedType, type HighlightMode, type SortOrder, type TableActionItem, type TableActions, type TableActionsBase, type TableActionsWithMinWidth, type TableBulkActions, type TableBulkGeneralAction, type TableBulkOverflowAction, type TableColumnBase, type TableColumnBaseWithMinWidthRequired, type TableColumn, type TableColumnTitleMenu, type TableColumnWithDataIndex, type TableColumnWithDataIndexAndMinWidth, type TableColumnWithMinWidth, type TableColumnWithRender, type TableColumnWithRenderAndMinWidth, type TableDataSource, type TableDataSourceWithId, type TableDataSourceWithKey, type TableCollectable, type TableDraggable, type TableExpandable, type TablePinnable, type TableRecord, type TableToggleable, type TableRowSelection, type TableRowSelectionBase, type TableRowSelectionCheckbox, type TableRowSelectionRadio, type TableScroll, type TableSelectionMode, type TableSize, } from '@mezzanine-ui/core/table';
1
+ export { TABLE_ACTIONS_KEY, tableClasses as classes, getCellAlignClass, getRowKey, type ColumnAlign, type FixedType, type HighlightMode, type SortOrder, type TableActionItem, type TableActions, type TableActionsBase, type TableActionsWithMinWidth, type TableBulkActions, type TableBulkGeneralAction, type TableBulkOverflowAction, type TableColumnBase, type TableColumnBaseWithMinWidthRequired, type TableColumn, type TableColumnTitleMenu, type TableColumnWithDataIndex, type TableColumnWithDataIndexAndMinWidth, type TableColumnWithMinWidth, type TableColumnWithRender, type TableColumnWithRenderAndMinWidth, type TableDataSource, type TableDataSourceWithId, type TableDataSourceWithKey, type TableCollectable, type TableDraggable, type TableExpandable, type TablePinnable, type TableRecord, type TableToggleable, type TableRowSelection, type TableRowSelectionBase, type TableRowState, type TableRowSelectionCheckbox, type TableRowSelectionRadio, type TableScroll, type TableSelectionMode, type TableSize, } from '@mezzanine-ui/core/table';
2
2
  export { default } from './Table';
3
3
  export type { TableBaseProps, TableDraggableOnlyProps, TableNoDragOrPinProps, TableNonResizableProps, TableNonVirtualizedProps, TablePinnableOnlyProps, TableProps, TableResizableProps, TableVirtualizedProps, } from './typings';
4
4
  export { TableContext, TableDataContext, TableSuperContext, useTableContext, useTableDataContext, useTableSuperContext, type TableResizedColumnState, type TableContextValue, type TableDataContextValue, type TableHighlightState, type TableExpansionState, type TableSelectionState, type TableSortingState, } from './TableContext';
@@ -1,4 +1,4 @@
1
- import type { HighlightMode, TableActions, TableActionsWithMinWidth, TableCollectable, TableColumn, TableColumnWithMinWidth, TableDataSource, TableDraggable, TableExpandable, TablePinnable, TableRowSelection, TableScroll, TableSize, TableToggleable } from '@mezzanine-ui/core/table';
1
+ import type { HighlightMode, TableActions, TableActionsWithMinWidth, TableCollectable, TableColumn, TableColumnWithMinWidth, TableDataSource, TableDraggable, TableExpandable, TablePinnable, TableRowSelection, TableRowState, TableScroll, TableSize, TableToggleable } from '@mezzanine-ui/core/table';
2
2
  import type { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
3
3
  import type { EmptyProps } from '../Empty';
4
4
  import type { TablePaginationProps } from './components/TablePagination';
@@ -47,6 +47,8 @@ export interface TableBaseProps<T extends TableDataSource = TableDataSource> ext
47
47
  rowHeightPreset?: 'base' | 'condensed' | 'detailed' | 'roomy';
48
48
  /** Row selection configuration */
49
49
  rowSelection?: TableRowSelection<T>;
50
+ /** Semantic state applied to each row. Accepts a state string or a function that receives the row data and returns a state string. */
51
+ rowState?: TableRowState | ((rowData: T) => TableRowState | undefined);
50
52
  /** Row indexes where a separator border should be displayed */
51
53
  separatorAtRowIndexes?: number[];
52
54
  /** Show header row */
@@ -39,6 +39,11 @@ export interface TextFieldBaseProps extends Omit<NativeElementPropsWithoutKeyAnd
39
39
  * @default false
40
40
  */
41
41
  forceShowClearable?: boolean;
42
+ /**
43
+ * Whether to hide the suffix when the clear button is visible.
44
+ * @default false
45
+ */
46
+ hideSuffixWhenClearable?: boolean;
42
47
  /**
43
48
  * Whether the field is in error state.
44
49
  * @default false
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import { textFieldClasses } from '@mezzanine-ui/core/text-field';
4
4
  import { forwardRef, useState, useRef, useEffect } from 'react';
5
5
  import ClearActions from '../ClearActions/ClearActions.js';
@@ -11,7 +11,7 @@ import cx from 'clsx';
11
11
  * The react component for `mezzanine` text field.
12
12
  */
13
13
  const TextField = forwardRef(function TextField(props, ref) {
14
- const { active = false, children, className, clearable = false, disabled, error = false, forceShowClearable = false, fullWidth = true, onClear, onClick: onClickProps, onKeyDown: onKeyDownProps, prefix, readonly, role: roleProp, size = 'main', suffix, typing: typingProp, warning, ...rest } = props;
14
+ const { active = false, children, className, clearable = false, disabled, error = false, forceShowClearable = false, fullWidth = true, hideSuffixWhenClearable = false, onClear, onClick: onClickProps, onKeyDown: onKeyDownProps, prefix, readonly, role: roleProp, size = 'main', suffix, typing: typingProp, warning, ...rest } = props;
15
15
  const [isTyping, setIsTyping] = useState(false);
16
16
  const [isHovered, setIsHovered] = useState(false);
17
17
  const [isFocused, setIsFocused] = useState(false);
@@ -117,11 +117,9 @@ const TextField = forwardRef(function TextField(props, ref) {
117
117
  [textFieldClasses.readonly]: readonly,
118
118
  [textFieldClasses.typing]: typing,
119
119
  [textFieldClasses.active]: active,
120
+ [textFieldClasses.clearing]: shouldShowClearable,
120
121
  [textFieldClasses.warning]: warning,
121
- }, className), children: [prefix && jsx("div", { className: textFieldClasses.prefix, children: prefix }), renderedChildren, clearable && (jsx(ClearActions, { type: "clearable", className: textFieldClasses.clearIcon, style: {
122
- opacity: shouldShowClearable ? 1 : 0,
123
- pointerEvents: shouldShowClearable ? 'auto' : 'none',
124
- }, onClick: (event) => {
122
+ }, className), children: [prefix && jsx("div", { className: textFieldClasses.prefix, children: prefix }), renderedChildren, clearable && !hideSuffixWhenClearable && (jsx(ClearActions, { type: "clearable", className: textFieldClasses.clearIcon, onClick: (event) => {
125
123
  if (!disabled && !readonly && onClear) {
126
124
  onClear(event);
127
125
  requestAnimationFrame(() => {
@@ -129,7 +127,15 @@ const TextField = forwardRef(function TextField(props, ref) {
129
127
  (_a = checkValueRef.current) === null || _a === void 0 ? void 0 : _a.call(checkValueRef);
130
128
  });
131
129
  }
132
- }, onMouseDown: (event) => event.preventDefault(), tabIndex: -1 })), suffix && jsx("div", { className: textFieldClasses.suffix, children: suffix })] }));
130
+ }, onMouseDown: (event) => event.preventDefault(), tabIndex: -1 })), suffix && (jsx("div", { className: cx(textFieldClasses.suffix, { [textFieldClasses.suffixOverlay]: hideSuffixWhenClearable }), children: hideSuffixWhenClearable ? (jsxs(Fragment, { children: [jsx("div", { className: textFieldClasses.suffixContent, children: suffix }), clearable && (jsx(ClearActions, { type: "clearable", className: textFieldClasses.clearIcon, onClick: (event) => {
131
+ if (!disabled && !readonly && onClear) {
132
+ onClear(event);
133
+ requestAnimationFrame(() => {
134
+ var _a;
135
+ (_a = checkValueRef.current) === null || _a === void 0 ? void 0 : _a.call(checkValueRef);
136
+ });
137
+ }
138
+ }, onMouseDown: (event) => event.preventDefault(), tabIndex: -1 }))] })) : suffix }))] }));
133
139
  });
134
140
 
135
141
  export { TextField as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mezzanine-ui/react",
3
- "version": "1.0.0-rc.2",
3
+ "version": "1.0.0-rc.3",
4
4
  "description": "React components for mezzanine-ui",
5
5
  "author": "Mezzanine",
6
6
  "repository": {
@@ -31,9 +31,9 @@
31
31
  "@floating-ui/dom": "^1.7.4",
32
32
  "@floating-ui/react-dom": "^2.1.6",
33
33
  "@hello-pangea/dnd": "^18.0.1",
34
- "@mezzanine-ui/core": "1.0.0-rc.2",
35
- "@mezzanine-ui/icons": "1.0.0-rc.2",
36
- "@mezzanine-ui/system": "1.0.0-rc.2",
34
+ "@mezzanine-ui/core": "1.0.0-rc.3",
35
+ "@mezzanine-ui/icons": "1.0.0-rc.3",
36
+ "@mezzanine-ui/system": "1.0.0-rc.3",
37
37
  "@tanstack/react-virtual": "^3.13.13",
38
38
  "@types/react-transition-group": "^4.4.12",
39
39
  "clsx": "^2.1.1",