@mezzanine-ui/react 1.0.0-beta.3 → 1.0.0-beta.5

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 (146) hide show
  1. package/AutoComplete/AutoComplete.d.ts +23 -0
  2. package/AutoComplete/AutoComplete.js +39 -9
  3. package/Breadcrumb/Breadcrumb.js +16 -21
  4. package/Breadcrumb/BreadcrumbDropdown.d.ts +11 -0
  5. package/Breadcrumb/BreadcrumbDropdown.js +22 -0
  6. package/Breadcrumb/BreadcrumbItem.d.ts +2 -3
  7. package/Breadcrumb/BreadcrumbItem.js +13 -31
  8. package/Breadcrumb/BreadcrumbOverflowMenu.d.ts +7 -0
  9. package/Breadcrumb/BreadcrumbOverflowMenu.js +77 -0
  10. package/Breadcrumb/BreadcrumbOverflowMenuDropdown.d.ts +11 -0
  11. package/Breadcrumb/BreadcrumbOverflowMenuDropdown.js +21 -0
  12. package/Breadcrumb/BreadcrumbOverflowMenuItem.d.ts +3 -0
  13. package/Breadcrumb/BreadcrumbOverflowMenuItem.js +27 -0
  14. package/Breadcrumb/typings.d.ts +21 -39
  15. package/Calendar/Calendar.js +2 -6
  16. package/Calendar/CalendarCell.d.ts +22 -0
  17. package/Calendar/CalendarCell.js +6 -2
  18. package/Calendar/CalendarControls.js +1 -1
  19. package/Calendar/CalendarDayOfWeek.js +3 -2
  20. package/Calendar/CalendarDays.js +5 -1
  21. package/Calendar/CalendarHalfYears.js +13 -7
  22. package/Calendar/CalendarMonths.js +13 -6
  23. package/Calendar/CalendarQuarters.js +13 -7
  24. package/Calendar/CalendarWeeks.js +87 -34
  25. package/Calendar/CalendarYears.js +13 -12
  26. package/Calendar/useCalendarControlModifiers.d.ts +1 -1
  27. package/Calendar/useCalendarControlModifiers.js +12 -12
  28. package/Calendar/useCalendarControls.d.ts +4 -4
  29. package/Calendar/useCalendarControls.js +33 -19
  30. package/Calendar/useRangeCalendarControls.d.ts +8 -8
  31. package/Calendar/useRangeCalendarControls.js +42 -31
  32. package/Checkbox/index.d.ts +4 -5
  33. package/Checkbox/index.js +1 -5
  34. package/ContentHeader/ContentHeader.d.ts +160 -0
  35. package/ContentHeader/ContentHeader.js +54 -0
  36. package/ContentHeader/index.d.ts +2 -0
  37. package/ContentHeader/index.js +1 -0
  38. package/ContentHeader/utils.d.ts +23 -0
  39. package/ContentHeader/utils.js +215 -0
  40. package/DateRangePicker/useDateRangeCalendarControls.js +8 -2
  41. package/Dropdown/Dropdown.d.ts +48 -0
  42. package/Dropdown/Dropdown.js +16 -2
  43. package/Dropdown/DropdownItem.d.ts +42 -0
  44. package/Dropdown/DropdownItem.js +144 -13
  45. package/Dropdown/DropdownItemCard.d.ts +7 -2
  46. package/Dropdown/DropdownItemCard.js +12 -9
  47. package/Empty/Empty.js +2 -1
  48. package/Empty/icons/EmptyMainNotificationIcon.d.ts +4 -0
  49. package/Empty/icons/EmptyMainNotificationIcon.js +9 -0
  50. package/Empty/typings.d.ts +2 -2
  51. package/FilterArea/Filter.d.ts +32 -0
  52. package/FilterArea/Filter.js +23 -0
  53. package/FilterArea/FilterArea.d.ts +58 -0
  54. package/FilterArea/FilterArea.js +31 -0
  55. package/FilterArea/FilterLine.d.ts +11 -0
  56. package/FilterArea/FilterLine.js +13 -0
  57. package/FilterArea/index.d.ts +6 -0
  58. package/FilterArea/index.js +3 -0
  59. package/Form/useSelectValueControl.d.ts +3 -4
  60. package/Form/useSelectValueControl.js +51 -39
  61. package/Input/Input.d.ts +6 -4
  62. package/Input/Input.js +28 -10
  63. package/Input/index.d.ts +1 -1
  64. package/Modal/MediaPreviewModal.d.ts +54 -0
  65. package/Modal/MediaPreviewModal.js +158 -0
  66. package/Modal/Modal.js +1 -1
  67. package/Modal/index.d.ts +2 -0
  68. package/Modal/index.js +1 -0
  69. package/Navigation/Navigation.js +6 -5
  70. package/Navigation/NavigationOption.d.ts +6 -2
  71. package/Navigation/NavigationOption.js +19 -9
  72. package/Navigation/NavigationOverflowMenu.d.ts +6 -0
  73. package/Navigation/NavigationOverflowMenu.js +90 -0
  74. package/Navigation/NavigationOverflowMenuOption.d.ts +7 -0
  75. package/Navigation/NavigationOverflowMenuOption.js +68 -0
  76. package/Navigation/NavigationUserMenu.d.ts +4 -2
  77. package/Navigation/NavigationUserMenu.js +13 -5
  78. package/Navigation/context.d.ts +3 -2
  79. package/NotificationCenter/NotificationCenter.d.ts +1 -1
  80. package/NotificationCenter/NotificationCenter.js +34 -14
  81. package/NotificationCenter/NotificationCenterDrawer.d.ts +20 -0
  82. package/PageHeader/PageHeader.d.ts +32 -25
  83. package/PageHeader/PageHeader.js +49 -35
  84. package/Popper/Popper.js +2 -1
  85. package/ResultState/ResultState.d.ts +9 -0
  86. package/ResultState/ResultState.js +36 -4
  87. package/Scrollbar/Scrollbar.d.ts +9 -0
  88. package/Scrollbar/Scrollbar.js +79 -0
  89. package/Scrollbar/index.d.ts +2 -0
  90. package/Scrollbar/index.js +1 -0
  91. package/Scrollbar/typings.d.ts +47 -0
  92. package/Select/Select.d.ts +37 -18
  93. package/Select/Select.js +165 -51
  94. package/Select/SelectTrigger.js +5 -4
  95. package/Select/index.d.ts +8 -9
  96. package/Select/index.js +3 -3
  97. package/Select/typings.d.ts +6 -1
  98. package/Selection/Selection.js +1 -1
  99. package/Selection/SelectionGroup.d.ts +28 -0
  100. package/Table/Table.d.ts +2 -120
  101. package/Table/Table.js +148 -53
  102. package/Table/TableContext.d.ts +11 -12
  103. package/Table/components/TableActionsCell.js +12 -4
  104. package/Table/components/TableBody.js +2 -1
  105. package/Table/components/TableColGroup.d.ts +1 -4
  106. package/Table/components/TableColGroup.js +15 -16
  107. package/Table/components/TableCollectableCell.d.ts +17 -0
  108. package/Table/components/TableCollectableCell.js +54 -0
  109. package/Table/components/TableDragOrPinHandleCell.d.ts +20 -0
  110. package/Table/components/TableDragOrPinHandleCell.js +58 -0
  111. package/Table/components/TableExpandedRow.js +11 -2
  112. package/Table/components/TableHeader.js +12 -10
  113. package/Table/components/TableRow.js +38 -13
  114. package/Table/components/TableSelectionCell.js +1 -1
  115. package/Table/components/TableToggleableCell.d.ts +16 -0
  116. package/Table/components/TableToggleableCell.js +51 -0
  117. package/Table/components/index.d.ts +4 -1
  118. package/Table/components/index.js +3 -0
  119. package/Table/hooks/typings.d.ts +18 -4
  120. package/Table/hooks/useTableExpansion.d.ts +2 -2
  121. package/Table/hooks/useTableExpansion.js +5 -5
  122. package/Table/hooks/useTableFixedOffsets.d.ts +6 -2
  123. package/Table/hooks/useTableFixedOffsets.js +58 -24
  124. package/Table/hooks/useTableScroll.d.ts +9 -3
  125. package/Table/hooks/useTableScroll.js +34 -7
  126. package/Table/hooks/useTableVirtualization.d.ts +2 -1
  127. package/Table/hooks/useTableVirtualization.js +2 -8
  128. package/Table/index.d.ts +4 -3
  129. package/Table/index.js +3 -0
  130. package/Table/typings.d.ts +172 -0
  131. package/Transition/Slide.d.ts +9 -2
  132. package/Transition/Slide.js +7 -4
  133. package/Tree/TreeNode.js +1 -1
  134. package/index.d.ts +4 -2
  135. package/index.js +6 -3
  136. package/package.json +6 -4
  137. package/Navigation/CollapsedMenu.d.ts +0 -6
  138. package/Navigation/CollapsedMenu.js +0 -16
  139. package/PageToolbar/PageToolbar.d.ts +0 -110
  140. package/PageToolbar/PageToolbar.js +0 -23
  141. package/PageToolbar/index.d.ts +0 -2
  142. package/PageToolbar/index.js +0 -1
  143. package/PageToolbar/utils.d.ts +0 -23
  144. package/PageToolbar/utils.js +0 -157
  145. package/Table/components/TableDragHandleCell.d.ts +0 -11
  146. package/Table/components/TableDragHandleCell.js +0 -44
@@ -40,6 +40,11 @@ export interface AutoCompleteBaseProps extends Omit<SelectTriggerProps, 'active'
40
40
  * @important When using with react-hook-form or native forms, this prop is recommended.
41
41
  */
42
42
  id?: string;
43
+ /**
44
+ * Whether to keep search text visible after blur when no value is selected.
45
+ * @default false
46
+ */
47
+ keepSearchTextOnBlur?: boolean;
43
48
  /**
44
49
  * The position of the input.
45
50
  * @default 'outside'
@@ -86,6 +91,10 @@ export interface AutoCompleteBaseProps extends Omit<SelectTriggerProps, 'active'
86
91
  * Can return a Promise for async data loading
87
92
  */
88
93
  onSearch?(input: string): void | Promise<void>;
94
+ /**
95
+ * Callback fired on every input change (no debounce).
96
+ */
97
+ onSearchTextChange?(text: string): void;
89
98
  /**
90
99
  * Callback fired when the dropdown visibility changes.
91
100
  */
@@ -135,6 +144,20 @@ export interface AutoCompleteBaseProps extends Omit<SelectTriggerProps, 'active'
135
144
  * @default '建立 "{text}"'
136
145
  */
137
146
  createActionTextTemplate?: string;
147
+ /**
148
+ * The z-index of the dropdown.
149
+ */
150
+ dropdownZIndex?: number | string;
151
+ /**
152
+ * Callback fired when the dropdown list reaches the bottom.
153
+ * Only fires when `menuMaxHeight` is set and the list is scrollable.
154
+ */
155
+ onReachBottom?: () => void;
156
+ /**
157
+ * Callback fired when the dropdown list leaves the bottom.
158
+ * Only fires when `menuMaxHeight` is set and the list is scrollable.
159
+ */
160
+ onLeaveBottom?: () => void;
138
161
  }
139
162
  export type AutoCompleteMultipleProps = AutoCompleteBaseProps & {
140
163
  /**
@@ -46,7 +46,7 @@ function isOptionSelected(option, value, isMultiple) {
46
46
  */
47
47
  const AutoComplete = forwardRef(function AutoComplete(props, ref) {
48
48
  const { disabled: disabledFromFormControl, fullWidth: fullWidthFromFormControl, required: requiredFromFormControl, severity, } = useContext(FormControlContext) || {};
49
- const { addable = false, asyncData = false, className, createSeparators = [',', '+', '\n'], defaultValue, disabled = disabledFromFormControl || false, disabledOptionsFilter = false, emptyText, error = severity === 'error' || false, fullWidth = fullWidthFromFormControl || false, id, inputPosition = 'outside', inputProps, inputRef, loading = false, loadingText, menuMaxHeight, mode = 'single', name, onClear: onClearProp, onChange: onChangeProp, onInsert, onSearch, onVisibilityChange, open: openProp, options: optionsProp, placeholder = '', prefix, required = requiredFromFormControl || false, searchDebounceTime = 300, searchTextControlRef, size, trimOnCreate = true, value: valueProp, createActionText, createActionTextTemplate = '建立 "{text}"', } = props;
49
+ const { addable = false, asyncData = false, className, createSeparators = [',', '+', '\n'], defaultValue, disabled = disabledFromFormControl || false, disabledOptionsFilter = false, emptyText, error = severity === 'error' || false, fullWidth = fullWidthFromFormControl || false, id, keepSearchTextOnBlur = false, inputPosition = 'outside', inputProps, inputRef, loading = false, loadingText, menuMaxHeight, mode = 'single', name, onClear: onClearProp, onChange: onChangeProp, onInsert, onSearch, onSearchTextChange, onVisibilityChange, open: openProp, options: optionsProp, placeholder = '', prefix, required = requiredFromFormControl || false, searchDebounceTime = 300, searchTextControlRef, size, trimOnCreate = true, value: valueProp, createActionText, createActionTextTemplate = '建立 "{text}"', dropdownZIndex, onReachBottom, onLeaveBottom, } = props;
50
50
  const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
51
51
  const isMultiple = mode === 'multiple';
52
52
  const isSingle = !isMultiple;
@@ -147,14 +147,15 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
147
147
  // In single mode, show searchText when focused, otherwise show selected value
148
148
  // In multiple mode, always return empty string to avoid displaying "0"
149
149
  const renderValue = useMemo(() => {
150
- if (isSingle && focused) {
150
+ if (isSingle
151
+ && (focused || (keepSearchTextOnBlur && !value && searchText))) {
151
152
  return () => searchText;
152
153
  }
153
154
  if (isMultiple) {
154
155
  return () => '';
155
156
  }
156
157
  return undefined;
157
- }, [focused, isMultiple, isSingle, searchText]);
158
+ }, [focused, isMultiple, isSingle, keepSearchTextOnBlur, searchText, value]);
158
159
  function getPlaceholder() {
159
160
  if (isSingle && focused && isSingleValue(value)) {
160
161
  return value.name;
@@ -167,6 +168,7 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
167
168
  /** should sync both search input and value */
168
169
  setSearchText(nextSearch);
169
170
  setInsertText(nextSearch);
171
+ onSearchTextChange === null || onSearchTextChange === void 0 ? void 0 : onSearchTextChange(nextSearch);
170
172
  if (autoSelectMatchingOption(nextSearch))
171
173
  return;
172
174
  if (!nextSearch) {
@@ -201,17 +203,33 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
201
203
  // Don't let Dropdown's onBlur close the dropdown when controlled
202
204
  // Only call onFocus(false) to update internal state
203
205
  onFocus(false);
206
+ // Clear search text and insert text when blur if keepSearchTextOnBlur is false
207
+ if (!keepSearchTextOnBlur) {
208
+ resetCreationInputs();
209
+ }
204
210
  (_a = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onBlur) === null || _a === void 0 ? void 0 : _a.call(inputProps, e);
205
211
  return;
206
212
  }
207
213
  // For uncontrolled mode, let Dropdown handle it normally
208
214
  // Dropdown's inlineTriggerElement will handle the blur and close logic
215
+ // Clear search text and insert text when blur if keepSearchTextOnBlur is false
216
+ if (!keepSearchTextOnBlur) {
217
+ resetCreationInputs();
218
+ }
209
219
  (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onBlur) === null || _b === void 0 ? void 0 : _b.call(inputProps, e);
210
220
  return;
211
221
  }
212
222
  onFocus(false);
223
+ // Clear search text and insert text when blur if keepSearchTextOnBlur is false
224
+ if (!keepSearchTextOnBlur) {
225
+ resetCreationInputs();
226
+ }
213
227
  (_c = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onBlur) === null || _c === void 0 ? void 0 : _c.call(inputProps, e);
214
228
  };
229
+ const handleClear = useCallback((e) => {
230
+ onClear(e);
231
+ resetCreationInputs();
232
+ }, [onClear, resetCreationInputs]);
215
233
  const onClickSuffixActionIcon = () => {
216
234
  toggleOpen((prev) => !prev);
217
235
  };
@@ -231,10 +249,10 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
231
249
  // Multiple mode: show checkbox at prepend
232
250
  // Single mode: show checked icon at append when selected
233
251
  if (mode === 'multiple') {
234
- result.checkSite = 'prepend';
252
+ result.checkSite = 'prefix';
235
253
  }
236
254
  else {
237
- result.checkSite = 'append';
255
+ result.checkSite = 'suffix';
238
256
  }
239
257
  // Set shortcutText to "New" for created items (persists even after selection)
240
258
  if (created) {
@@ -267,14 +285,21 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
267
285
  const handleDropdownSelect = useCallback((option) => {
268
286
  const selectedValue = options.find((opt) => opt.id === option.id);
269
287
  if (selectedValue) {
270
- wrappedOnChange(selectedValue);
271
288
  // Close dropdown after selection in single mode
272
289
  if (mode === 'single') {
290
+ // Update searchText first to prevent showing old value
291
+ setSearchText(selectedValue.name);
292
+ setInsertText(selectedValue.name);
293
+ // Then update value and focus state
294
+ wrappedOnChange(selectedValue);
273
295
  toggleOpen(false);
274
296
  onFocus(false);
275
297
  }
298
+ else {
299
+ wrappedOnChange(selectedValue);
300
+ }
276
301
  }
277
- }, [mode, onFocus, options, toggleOpen, wrappedOnChange]);
302
+ }, [mode, onFocus, options, setSearchText, setInsertText, toggleOpen, wrappedOnChange]);
278
303
  // Active index for dropdown keyboard navigation
279
304
  const [activeIndex, setActiveIndex] = useState(null);
280
305
  const setListboxHasVisualFocus = useCallback(() => { }, []);
@@ -349,10 +374,13 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
349
374
  return false;
350
375
  if (isSingle) {
351
376
  if (!value) {
377
+ // Update searchText first to prevent showing old value
378
+ setSearchText(matchingOption.name);
379
+ setInsertText(matchingOption.name);
380
+ // Then update value and focus state
352
381
  wrappedOnChange(matchingOption);
353
382
  toggleOpen(false);
354
383
  onFocus(false);
355
- resetCreationInputs();
356
384
  return true;
357
385
  }
358
386
  return false;
@@ -371,6 +399,8 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
371
399
  onFocus,
372
400
  options,
373
401
  resetCreationInputs,
402
+ setSearchText,
403
+ setInsertText,
374
404
  toggleOpen,
375
405
  value,
376
406
  wrappedOnChange,
@@ -400,7 +430,7 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
400
430
  : createActionTextTemplate.replace('{text}', insertText))
401
431
  : undefined, activeIndex: activeIndex, disabled: isInputDisabled, emptyText: emptyText, followText: searchText, inputPosition: inputPosition, isMatchInputValue: true, listboxId: menuId, loadingText: loadingText, maxHeight: menuMaxHeight, mode: mode, onActionCustom: shouldShowCreateAction
402
432
  ? handleActionCustom
403
- : undefined, onItemHover: setActiveIndex, onSelect: handleDropdownSelect, onVisibilityChange: handleVisibilityChange, open: open, options: dropdownOptionsForRender, placement: "bottom", sameWidth: true, showDropdownActions: shouldShowCreateAction, showActionShowTopBar: shouldShowCreateAction, status: dropdownStatus, type: "default", value: dropdownValue, children: jsx(SelectTrigger, { ref: composedRef, active: open, className: className, clearable: true, disabled: isInputDisabled, fullWidth: fullWidth, inputRef: inputRef, mode: mode, onTagClose: wrappedOnChange, onClear: onClear, placeholder: getPlaceholder(), prefix: prefix, readOnly: false, required: required, type: error ? 'error' : 'default', inputProps: {
433
+ : undefined, onItemHover: setActiveIndex, onSelect: handleDropdownSelect, onVisibilityChange: handleVisibilityChange, open: open, options: dropdownOptionsForRender, placement: "bottom", sameWidth: true, showDropdownActions: shouldShowCreateAction, showActionShowTopBar: shouldShowCreateAction, status: dropdownStatus, type: "default", value: dropdownValue, zIndex: dropdownZIndex, onReachBottom: onReachBottom, onLeaveBottom: onLeaveBottom, children: jsx(SelectTrigger, { ref: composedRef, active: open, className: className, clearable: true, isForceClearable: true, disabled: isInputDisabled, fullWidth: fullWidth, inputRef: inputRef, mode: mode, onTagClose: wrappedOnChange, onClear: handleClear, placeholder: getPlaceholder(), prefix: prefix, readOnly: false, required: required, type: error ? 'error' : 'default', inputProps: {
404
434
  ...resolvedInputProps,
405
435
  onClick: (e) => {
406
436
  var _a;
@@ -1,9 +1,10 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { forwardRef, isValidElement, cloneElement } from 'react';
3
- import { SlashIcon } from '@mezzanine-ui/icons';
4
3
  import { breadcrumbClasses } from '@mezzanine-ui/core/breadcrumb';
5
- import BreadcrumbItem from './BreadcrumbItem.js';
4
+ import { SlashIcon } from '@mezzanine-ui/icons';
6
5
  import { flattenChildren } from '../utils/flatten-children.js';
6
+ import BreadcrumbItem from './BreadcrumbItem.js';
7
+ import { BreadcrumbOverflowMenu } from './BreadcrumbOverflowMenu.js';
7
8
  import Icon from '../Icon/Icon.js';
8
9
  import cx from 'clsx';
9
10
 
@@ -13,32 +14,26 @@ const renderItemWithProps = (item, appendProps) => {
13
14
  }
14
15
  return jsx(BreadcrumbItem, { ...item, ...appendProps });
15
16
  };
17
+ const convertToPropsWithId = (item) => {
18
+ if (isValidElement(item)) {
19
+ return { id: item.props.id || item.props.name, ...item.props };
20
+ }
21
+ return { id: item.id || item.name, ...item };
22
+ };
16
23
  const renderItems = (items, condensed) => {
17
24
  if (!items) {
18
25
  return null;
19
26
  }
20
27
  const lastIndex = items.length - 1;
28
+ const hasOverflowDropdownIcon = !condensed || items.length > 2;
29
+ const collapsedProps = hasOverflowDropdownIcon
30
+ ? condensed
31
+ ? items.map((v) => convertToPropsWithId(v)).slice(0, lastIndex - 1)
32
+ : items.map((v) => convertToPropsWithId(v)).slice(2, lastIndex - 1)
33
+ : [];
21
34
  return (jsxs(Fragment, { children: [!condensed &&
22
35
  lastIndex >= 0 &&
23
- renderItemWithProps(items[0], { current: lastIndex === 0 }), !condensed && lastIndex >= 1 && (jsxs(Fragment, { children: [jsx(Icon, { icon: SlashIcon, size: 14 }), renderItemWithProps(items[1], { current: lastIndex === 1 })] })), !condensed && items.length <= 4 && (jsxs(Fragment, { children: [lastIndex >= 2 && (jsxs(Fragment, { children: [jsx(Icon, { icon: SlashIcon, size: 14 }), renderItemWithProps(items[2], { current: lastIndex === 2 })] })), lastIndex === 3 && (jsxs(Fragment, { children: [jsx(Icon, { icon: SlashIcon, size: 14 }), renderItemWithProps(items[3], { current: true })] }))] })), (items.length > 4 || condensed) && (jsxs(Fragment, { children: [!condensed && jsx(Icon, { icon: SlashIcon, size: 14 }), (!condensed || items.length > 2) && (jsxs(Fragment, { children: [jsx(BreadcrumbItem, { options: (condensed
24
- ? items.slice(0, lastIndex - 1)
25
- : items.slice(2, lastIndex - 1)).map((item) => {
26
- if (isValidElement(item)) {
27
- const { props } = item;
28
- return {
29
- label: props.label,
30
- href: props.href,
31
- target: props.target,
32
- id: props.id,
33
- };
34
- }
35
- return {
36
- label: item.label,
37
- href: item.href,
38
- target: item.target,
39
- id: item.id,
40
- };
41
- }) }), jsx(Icon, { icon: SlashIcon, size: 14 })] })), lastIndex - 1 >= 0 && (jsxs(Fragment, { children: [renderItemWithProps(items[lastIndex - 1]), jsx(Icon, { icon: SlashIcon, size: 14 })] })), renderItemWithProps(items[lastIndex], { current: true })] }))] }));
36
+ renderItemWithProps(items[0], { current: lastIndex === 0 }), !condensed && lastIndex >= 1 && (jsxs(Fragment, { children: [jsx(Icon, { icon: SlashIcon, size: 14 }), renderItemWithProps(items[1], { current: lastIndex === 1 })] })), !condensed && items.length <= 4 && (jsxs(Fragment, { children: [lastIndex >= 2 && (jsxs(Fragment, { children: [jsx(Icon, { icon: SlashIcon, size: 14 }), renderItemWithProps(items[2], { current: lastIndex === 2 })] })), lastIndex === 3 && (jsxs(Fragment, { children: [jsx(Icon, { icon: SlashIcon, size: 14 }), renderItemWithProps(items[3], { current: true })] }))] })), (items.length > 4 || condensed) && (jsxs(Fragment, { children: [!condensed && jsx(Icon, { icon: SlashIcon, size: 14 }), hasOverflowDropdownIcon && (jsxs(Fragment, { children: [jsx(BreadcrumbOverflowMenu, { collapsedProps: collapsedProps }), jsx(Icon, { icon: SlashIcon, size: 14 })] })), lastIndex - 1 >= 0 && (jsxs(Fragment, { children: [renderItemWithProps(items[lastIndex - 1]), jsx(Icon, { icon: SlashIcon, size: 14 })] })), renderItemWithProps(items[lastIndex], { current: true })] }))] }));
42
37
  };
43
38
  /**
44
39
  * The react component for `mezzanine` breadcrumb.
@@ -0,0 +1,11 @@
1
+ declare const BreadcrumbDropdown: import("react").ForwardRefExoticComponent<Omit<import("../Dropdown").DropdownProps, "children"> & {
2
+ className?: string;
3
+ current?: boolean;
4
+ href?: never;
5
+ id?: string;
6
+ name: string;
7
+ onClick?: () => void;
8
+ open?: boolean;
9
+ target?: never;
10
+ } & import("react").RefAttributes<HTMLSpanElement>>;
11
+ export default BreadcrumbDropdown;
@@ -0,0 +1,22 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { forwardRef, useState } from 'react';
3
+ import { ChevronDownIcon } from '@mezzanine-ui/icons';
4
+ import { breadcrumbItemClasses } from '@mezzanine-ui/core/breadcrumb';
5
+ import Typography from '../Typography/Typography.js';
6
+ import Dropdown from '../Dropdown/Dropdown.js';
7
+ import Rotate from '../Transition/Rotate.js';
8
+ import Icon from '../Icon/Icon.js';
9
+ import cx from 'clsx';
10
+
11
+ const BreadcrumbDropdown = forwardRef(function BreadcrumbDropdown(props, ref) {
12
+ const { className, current, name, onClick, open: openProp, options, ...rest } = props;
13
+ const [_open, setOpen] = useState(false);
14
+ const open = openProp !== null && openProp !== void 0 ? openProp : _open;
15
+ const handleClick = () => {
16
+ setOpen(!open);
17
+ onClick === null || onClick === void 0 ? void 0 : onClick();
18
+ };
19
+ return (jsx("span", { className: cx(breadcrumbItemClasses.host, className), ref: ref, children: jsx(Dropdown, { onClose: () => setOpen(false), onOpen: () => handleClick(), options: options, placement: "bottom-start", ...rest, children: jsxs("button", { className: cx(breadcrumbItemClasses.trigger, open && breadcrumbItemClasses.expanded, current && breadcrumbItemClasses.current), type: "button", children: [name && (jsx(Typography, { variant: current ? 'caption-highlight' : 'caption', children: name })), jsx(Rotate, { in: open, children: jsx(Icon, { className: breadcrumbItemClasses.icon, icon: ChevronDownIcon, size: 14 }) })] }) }) }));
20
+ });
21
+
22
+ export { BreadcrumbDropdown as default };
@@ -1,4 +1,3 @@
1
- declare const BreadcrumbItem: import("react").ForwardRefExoticComponent<Omit<Omit<import("..").ComponentPropsWithoutKeyAndRef<"button">, "expand" | "label" | "component" | "current" | "options" | "href" | "target"> & (import("./typings").BreadcrumbDropdownItemProps | import("./typings").BreadcrumbItemTextProps | import("./typings").BreadcrumbLinkItemProps), "component"> & {
2
- component?: import("./typings").BreadcrumbItemComponent | undefined;
3
- } & import("react").RefAttributes<HTMLElement>>;
1
+ import type { BreadcrumbItemProps } from './typings';
2
+ declare const BreadcrumbItem: import("react").ForwardRefExoticComponent<BreadcrumbItemProps & import("react").RefAttributes<HTMLSpanElement>>;
4
3
  export default BreadcrumbItem;
@@ -1,45 +1,27 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { forwardRef, useState } from 'react';
3
- import { ChevronDownIcon, DotHorizontalIcon } from '@mezzanine-ui/icons';
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { forwardRef } from 'react';
4
3
  import { breadcrumbItemClasses } from '@mezzanine-ui/core/breadcrumb';
5
4
  import Typography from '../Typography/Typography.js';
6
- import Rotate from '../Transition/Rotate.js';
7
- import Icon from '../Icon/Icon.js';
8
- import Menu from '../Menu/Menu.js';
9
- import MenuItem from '../Menu/MenuItem.js';
5
+ import BreadcrumbDropdown from './BreadcrumbDropdown.js';
10
6
  import cx from 'clsx';
11
7
 
12
8
  const BreadcrumbItem = forwardRef(function BreadcrumbItem(props, ref) {
13
- const { className, component, current, expand: expandProp, label, onClick, onTouchEnd, options, ...rest } = props;
14
- const [_expand, setExpand] = useState(false);
15
- const expand = expandProp !== null && expandProp !== void 0 ? expandProp : _expand;
16
- const Component = (() => {
9
+ if ('options' in props)
10
+ return jsx(BreadcrumbDropdown, { ...props });
11
+ const { className, component, current, href, name, onClick, rel, target, ...rest } = props;
12
+ const TriggerComponent = (() => {
17
13
  if (component)
18
14
  return component;
19
- if ('onClick' in props || 'options' in props) {
20
- return 'button';
21
- }
22
- if (!current && 'href' in props && typeof props.href === 'string') {
15
+ if ((!current && 'href' in props && typeof props.href === 'string') ||
16
+ 'onClick' in props) {
23
17
  return 'a';
24
18
  }
25
- return 'div';
19
+ return 'span';
26
20
  })();
27
- const handleClick = (e) => {
28
- setExpand(!expand);
29
- onClick === null || onClick === void 0 ? void 0 : onClick(e);
30
- };
31
- const handleTouchEnd = (e) => {
32
- setExpand(!expand);
33
- onTouchEnd === null || onTouchEnd === void 0 ? void 0 : onTouchEnd(e);
21
+ const handleClick = () => {
22
+ onClick === null || onClick === void 0 ? void 0 : onClick();
34
23
  };
35
- return (jsxs(Component, { ...rest, "aria-expanded": options ? expand : undefined, "aria-haspopup": options ? 'true' : undefined, className: cx(breadcrumbItemClasses.host, expand && breadcrumbItemClasses.expanded, current && breadcrumbItemClasses.current, className), onClick: Component === 'button' ? handleClick : undefined, onTouchEnd: Component === 'button' ? handleTouchEnd : undefined, ref: ref, children: [label && (jsx(Typography, { variant: current ? 'caption-highlight' : 'caption', children: label })), 'options' in props &&
36
- (label ? (
37
- /* normal dropdown icon item */
38
- jsx(Rotate, { in: expand, children: jsx(Icon, { className: breadcrumbItemClasses.icon, icon: ChevronDownIcon, size: 14 }) })) : (
39
- /* overflow dropdown icon item */
40
- jsx(Icon, { className: breadcrumbItemClasses.icon, icon: DotHorizontalIcon, size: 14 }))), options && expand && (jsx(Menu, { className: breadcrumbItemClasses.menu, children: options
41
- .filter((v) => v.label)
42
- .map((option) => (jsx(MenuItem, { children: option.label }, option.id || option.label))) }))] }));
24
+ return (jsx("span", { ...rest, className: cx(breadcrumbItemClasses.host, className), ref: ref, children: jsx(TriggerComponent, { className: cx(breadcrumbItemClasses.trigger, current && breadcrumbItemClasses.current), href: TriggerComponent === 'a' ? href : undefined, onClick: TriggerComponent === 'a' ? handleClick : undefined, rel: TriggerComponent === 'a' ? rel : undefined, target: TriggerComponent === 'a' ? target : undefined, children: name && (jsx(Typography, { variant: current ? 'caption-highlight' : 'caption', children: name })) }) }));
43
25
  });
44
26
 
45
27
  export { BreadcrumbItem as default };
@@ -0,0 +1,7 @@
1
+ import { HtmlHTMLAttributes } from 'react';
2
+ import { BreadcrumbItemProps } from './typings';
3
+ export declare const BreadcrumbOverflowMenu: (props: HtmlHTMLAttributes<HTMLButtonElement> & {
4
+ collapsedProps: (BreadcrumbItemProps & {
5
+ id: string;
6
+ })[];
7
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,77 @@
1
+ 'use client';
2
+ import { useState, useRef, useMemo, useCallback, createElement } from 'react';
3
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
4
+ import { TransitionGroup } from 'react-transition-group';
5
+ import { breadcrumbClasses } from '@mezzanine-ui/core/breadcrumb';
6
+ import { DotHorizontalIcon } from '@mezzanine-ui/icons';
7
+ import { MOTION_EASING, MOTION_DURATION } from '@mezzanine-ui/system/motion';
8
+ import { useDocumentEvents } from '../hooks/useDocumentEvents.js';
9
+ import BreadcrumbOverflowMenuItem from './BreadcrumbOverflowMenuItem.js';
10
+ import Icon from '../Icon/Icon.js';
11
+ import Popper from '../Popper/Popper.js';
12
+ import Translate from '../Transition/Translate.js';
13
+ import cx from 'clsx';
14
+
15
+ const BreadcrumbOverflowMenu = (props) => {
16
+ const { onClick, className, collapsedProps, ...rest } = props;
17
+ const [menuOpen, setMenuOpen] = useState(false);
18
+ const targetRef = useRef(null);
19
+ const popperRef = useRef(null);
20
+ const translateProps = useMemo(() => ({
21
+ duration: {
22
+ enter: MOTION_DURATION.moderate,
23
+ exit: MOTION_DURATION.moderate,
24
+ },
25
+ easing: {
26
+ enter: MOTION_EASING.standard,
27
+ exit: MOTION_EASING.standard,
28
+ },
29
+ }), []);
30
+ useDocumentEvents(() => {
31
+ if (!menuOpen) {
32
+ return;
33
+ }
34
+ const handleClickAway = (event) => {
35
+ const target = event.target;
36
+ const anchor = targetRef.current;
37
+ const popper = popperRef.current;
38
+ if (!target)
39
+ return;
40
+ if (anchor &&
41
+ popper &&
42
+ !anchor.contains(target) &&
43
+ !popper.contains(target)) {
44
+ setMenuOpen(false);
45
+ }
46
+ };
47
+ return {
48
+ click: handleClickAway,
49
+ touchend: handleClickAway,
50
+ };
51
+ }, [menuOpen]);
52
+ const zIndexMiddleware = useMemo(() => {
53
+ const zIndexValue = 1;
54
+ return {
55
+ name: 'zIndex',
56
+ fn: ({ elements }) => {
57
+ const zIndexNum = zIndexValue
58
+ ;
59
+ Object.assign(elements.floating.style, {
60
+ zIndex: zIndexNum,
61
+ });
62
+ return {};
63
+ },
64
+ };
65
+ }, []);
66
+ const buttonOnClick = useCallback((e) => {
67
+ setMenuOpen(!menuOpen);
68
+ onClick === null || onClick === void 0 ? void 0 : onClick(e);
69
+ }, [menuOpen, onClick]);
70
+ return (jsxs(Fragment, { children: [jsx("button", { "aria-label": 'more options', type: "button", ...rest, ref: targetRef, className: cx(breadcrumbClasses.iconButton, className), onClick: buttonOnClick, children: jsx(Icon, { icon: DotHorizontalIcon, size: 14 }) }), jsx(Popper, { anchor: targetRef.current, disablePortal: true, open: menuOpen, options: {
71
+ middleware: [zIndexMiddleware],
72
+ placement: 'bottom-start',
73
+ }, ref: popperRef, children: jsx(TransitionGroup, { component: null, children: menuOpen && (createElement(Translate, { ...translateProps, from: 'bottom', in: true, key: "popper-list" },
74
+ jsx("span", { className: breadcrumbClasses.menu, children: jsx("span", { className: breadcrumbClasses.menuContent, children: collapsedProps.map((v) => (jsx(BreadcrumbOverflowMenuItem, { ...v }, v.id))) }) }))) }) })] }));
75
+ };
76
+
77
+ export { BreadcrumbOverflowMenu };
@@ -0,0 +1,11 @@
1
+ declare const BreadcrumbOverflowMenuDropdown: import("react").ForwardRefExoticComponent<Omit<import("../Dropdown").DropdownProps, "children"> & {
2
+ className?: string;
3
+ current?: boolean;
4
+ href?: never;
5
+ id?: string;
6
+ name: string;
7
+ onClick?: () => void;
8
+ open?: boolean;
9
+ target?: never;
10
+ } & import("react").RefAttributes<HTMLSpanElement>>;
11
+ export default BreadcrumbOverflowMenuDropdown;
@@ -0,0 +1,21 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { forwardRef, useState } from 'react';
3
+ import { breadcrumbOverflowMenuItemClasses } from '@mezzanine-ui/core/breadcrumb';
4
+ import { ChevronRightIcon } from '@mezzanine-ui/icons';
5
+ import Typography from '../Typography/Typography.js';
6
+ import Dropdown from '../Dropdown/Dropdown.js';
7
+ import Icon from '../Icon/Icon.js';
8
+ import cx from 'clsx';
9
+
10
+ const BreadcrumbOverflowMenuDropdown = forwardRef(function BreadcrumbOverflowMenuDropdown(props, ref) {
11
+ const { className, name, onClick, open: openProp, options, ...rest } = props;
12
+ const [_open, setOpen] = useState(false);
13
+ const open = openProp !== null && openProp !== void 0 ? openProp : _open;
14
+ const handleClick = () => {
15
+ setOpen(!open);
16
+ onClick === null || onClick === void 0 ? void 0 : onClick();
17
+ };
18
+ return (jsx("span", { className: cx(breadcrumbOverflowMenuItemClasses.host, open && breadcrumbOverflowMenuItemClasses.expanded, className), ref: ref, children: jsx(Dropdown, { onClose: () => setOpen(false), onOpen: () => handleClick(), options: options, placement: "right-start", ...rest, children: jsxs("button", { className: cx(breadcrumbOverflowMenuItemClasses.trigger), type: "button", children: [jsx(Typography, { variant: 'label-primary', children: name }), jsx(Icon, { className: breadcrumbOverflowMenuItemClasses.icon, icon: ChevronRightIcon, size: 16 })] }) }) }));
19
+ });
20
+
21
+ export { BreadcrumbOverflowMenuDropdown as default };
@@ -0,0 +1,3 @@
1
+ import type { BreadcrumbItemProps } from './typings';
2
+ declare const BreadcrumbOverflowMenuItem: import("react").ForwardRefExoticComponent<BreadcrumbItemProps & import("react").RefAttributes<HTMLSpanElement>>;
3
+ export default BreadcrumbOverflowMenuItem;
@@ -0,0 +1,27 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { forwardRef } from 'react';
3
+ import { breadcrumbOverflowMenuItemClasses } from '@mezzanine-ui/core/breadcrumb';
4
+ import Typography from '../Typography/Typography.js';
5
+ import BreadcrumbOverflowMenuDropdown from './BreadcrumbOverflowMenuDropdown.js';
6
+ import cx from 'clsx';
7
+
8
+ const BreadcrumbOverflowMenuItem = forwardRef(function BreadcrumbOverflowMenuItem(props, ref) {
9
+ if ('options' in props)
10
+ return jsx(BreadcrumbOverflowMenuDropdown, { ...props });
11
+ const { className, component, current, href, name, onClick, rel, target, ...rest } = props;
12
+ const TriggerComponent = (() => {
13
+ if (component)
14
+ return component;
15
+ if ((!current && 'href' in props && typeof props.href === 'string') ||
16
+ 'onClick' in props) {
17
+ return 'a';
18
+ }
19
+ return 'span';
20
+ })();
21
+ const handleClick = () => {
22
+ onClick === null || onClick === void 0 ? void 0 : onClick();
23
+ };
24
+ return (jsx("span", { ...rest, className: cx(breadcrumbOverflowMenuItemClasses.host, className), ref: ref, children: jsx(TriggerComponent, { className: cx(breadcrumbOverflowMenuItemClasses.trigger), href: TriggerComponent === 'a' ? href : undefined, onClick: TriggerComponent === 'a' ? handleClick : undefined, rel: TriggerComponent === 'a' ? rel : undefined, target: TriggerComponent === 'a' ? target : undefined, children: jsx(Typography, { variant: 'label-primary', children: name }) }) }));
25
+ });
26
+
27
+ export { BreadcrumbOverflowMenuItem as default };
@@ -1,5 +1,6 @@
1
1
  import type { JSXElementConstructor, ReactElement } from 'react';
2
2
  import type { ComponentOverridableForwardRefComponentPropsFactory, NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
3
+ import type { DropdownProps } from '../Dropdown';
3
4
  export type BreadcrumbProps = Omit<NativeElementPropsWithoutKeyAndRef<'nav'>, 'children'> & ({
4
5
  /**
5
6
  * Display only the last two items with an ellipsis dropdown for all previous items
@@ -12,64 +13,45 @@ export type BreadcrumbProps = Omit<NativeElementPropsWithoutKeyAndRef<'nav'>, 'c
12
13
  items?: never;
13
14
  children: ReactElement<BreadcrumbItemProps> | ReactElement<BreadcrumbItemProps>[];
14
15
  });
15
- export type BreadcrumbItemComponent = 'a' | 'button' | JSXElementConstructor<any>;
16
- export type BreadcrumbItemProps<C extends BreadcrumbItemComponent = 'button'> = ComponentOverridableForwardRefComponentPropsFactory<BreadcrumbItemComponent, C, BreadcrumbDropdownItemProps | BreadcrumbItemTextProps | BreadcrumbLinkItemProps>;
17
- export type BreadcrumbDropdownItemProps = Omit<NativeElementPropsWithoutKeyAndRef<'button'>, 'children'> & {
18
- component?: 'button';
19
- /**
20
- * Whether is the current page item.
21
- */
22
- current?: boolean;
23
- /**
24
- * Whether to expand the dropdown item icon.
25
- */
26
- expand?: boolean;
27
- href?: string;
28
- label?: string;
29
- /**
30
- * The dropdown options.
31
- */
32
- options: Array<{
33
- /**
34
- * The href of dropdown item.
35
- */
36
- href?: string;
37
- id?: string;
38
- /**
39
- * The content of dropdown item.
40
- */
41
- label?: string;
42
- target?: '_blank' | '_parent' | '_self' | '_top' | string;
43
- }>;
44
- target?: '_blank' | '_parent' | '_self' | '_top' | string;
45
- };
16
+ export type BreadcrumbItemComponent = 'a' | 'span' | JSXElementConstructor<any>;
17
+ export type BreadcrumbItemProps<C extends BreadcrumbItemComponent = 'span'> = Omit<ComponentOverridableForwardRefComponentPropsFactory<BreadcrumbItemComponent, C, BreadcrumbItemTextProps | BreadcrumbLinkItemProps>, 'children' | 'onSelect'> | BreadcrumbDropdownProps;
46
18
  export type BreadcrumbItemTextProps = {
47
- component?: 'div';
19
+ component?: 'span';
48
20
  /**
49
21
  * Whether is the current page item.
50
22
  */
51
23
  current?: boolean;
52
- expand?: never;
53
24
  href?: never;
25
+ id?: string;
54
26
  /**
55
- * The content of breadcrumb text.
27
+ * The content of breadcrumb item text.
56
28
  */
57
- label: string;
58
- options?: never;
29
+ name: string;
30
+ onClick?: never;
59
31
  target?: never;
60
32
  };
61
33
  export type BreadcrumbLinkItemProps = Omit<NativeElementPropsWithoutKeyAndRef<'a'>, 'children'> & {
62
34
  component?: 'a';
63
35
  current?: boolean;
64
- expand?: never;
65
36
  /**
66
37
  * The href of breadcrumb link.
67
38
  */
68
39
  href: string;
69
- label: string;
70
- options?: never;
40
+ id?: string;
41
+ name: string;
42
+ onClick?: () => void;
71
43
  /**
72
44
  * The target attribute specifies where to open the linked document.
73
45
  */
74
46
  target?: '_blank' | '_parent' | '_self' | '_top' | string;
75
47
  };
48
+ export type BreadcrumbDropdownProps = Omit<DropdownProps, 'children'> & {
49
+ className?: string;
50
+ current?: boolean;
51
+ href?: never;
52
+ id?: string;
53
+ name: string;
54
+ onClick?: () => void;
55
+ open?: boolean;
56
+ target?: never;
57
+ };
@@ -93,9 +93,7 @@ const Calendar = forwardRef(function Calendar(props, ref) {
93
93
  ? () => {
94
94
  onDoubleNext(mode);
95
95
  }
96
- : undefined, onNext:
97
- // Only day and week modes have single next/prev (for month navigation)
98
- onNext && (mode === 'day' || mode === 'week')
96
+ : undefined, onNext: onNext
99
97
  ? () => {
100
98
  onNext(mode);
101
99
  }
@@ -103,9 +101,7 @@ const Calendar = forwardRef(function Calendar(props, ref) {
103
101
  ? () => {
104
102
  onDoublePrev(mode);
105
103
  }
106
- : undefined, onPrev:
107
- // Only day and week modes have single next/prev (for month navigation)
108
- onPrev && (mode === 'day' || mode === 'week')
104
+ : undefined, onPrev: onPrev
109
105
  ? () => {
110
106
  onPrev(mode);
111
107
  }