@mezzanine-ui/react 1.0.0-beta.6 → 1.0.0-beta.7

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 (142) hide show
  1. package/Accordion/Accordion.d.ts +23 -1
  2. package/Accordion/Accordion.js +59 -11
  3. package/Accordion/AccordionActions.d.ts +13 -0
  4. package/Accordion/AccordionActions.js +24 -0
  5. package/Accordion/AccordionContent.d.ts +9 -0
  6. package/Accordion/{AccordionDetails.js → AccordionContent.js} +4 -6
  7. package/Accordion/AccordionControlContext.d.ts +2 -2
  8. package/Accordion/AccordionGroup.d.ts +10 -0
  9. package/Accordion/AccordionGroup.js +26 -0
  10. package/Accordion/AccordionTitle.d.ts +14 -0
  11. package/Accordion/AccordionTitle.js +56 -0
  12. package/Accordion/index.d.ts +8 -4
  13. package/Accordion/index.js +4 -2
  14. package/AutoComplete/AutoComplete.d.ts +20 -6
  15. package/AutoComplete/AutoComplete.js +118 -30
  16. package/Backdrop/Backdrop.js +15 -19
  17. package/Calendar/CalendarDays.js +1 -1
  18. package/Card/BaseCard.d.ts +11 -0
  19. package/Card/BaseCard.js +48 -0
  20. package/Card/BaseCardSkeleton.d.ts +14 -0
  21. package/Card/BaseCardSkeleton.js +18 -0
  22. package/Card/CardGroup.d.ts +47 -0
  23. package/Card/CardGroup.js +147 -0
  24. package/Card/FourThumbnailCard.d.ts +14 -0
  25. package/Card/FourThumbnailCard.js +73 -0
  26. package/Card/FourThumbnailCardSkeleton.d.ts +14 -0
  27. package/Card/FourThumbnailCardSkeleton.js +20 -0
  28. package/Card/QuickActionCard.d.ts +12 -0
  29. package/Card/QuickActionCard.js +23 -0
  30. package/Card/QuickActionCardSkeleton.d.ts +14 -0
  31. package/Card/QuickActionCardSkeleton.js +18 -0
  32. package/Card/SingleThumbnailCard.d.ts +13 -0
  33. package/Card/SingleThumbnailCard.js +44 -0
  34. package/Card/SingleThumbnailCardSkeleton.d.ts +19 -0
  35. package/Card/SingleThumbnailCardSkeleton.js +18 -0
  36. package/Card/Thumbnail.d.ts +12 -0
  37. package/Card/Thumbnail.js +18 -0
  38. package/Card/ThumbnailCardInfo.d.ts +34 -0
  39. package/Card/ThumbnailCardInfo.js +43 -0
  40. package/Card/index.d.ts +43 -4
  41. package/Card/index.js +19 -2
  42. package/Card/typings.d.ts +442 -0
  43. package/Checkbox/Checkbox.d.ts +8 -0
  44. package/Checkbox/Checkbox.js +3 -2
  45. package/Checkbox/CheckboxGroup.js +1 -1
  46. package/ContentHeader/ContentHeader.d.ts +22 -70
  47. package/ContentHeader/ContentHeader.js +1 -1
  48. package/ContentHeader/ContentHeaderResponsive.d.ts +9 -0
  49. package/ContentHeader/ContentHeaderResponsive.js +7 -0
  50. package/ContentHeader/utils.d.ts +3 -3
  51. package/ContentHeader/utils.js +66 -20
  52. package/Cropper/Cropper.d.ts +66 -0
  53. package/Cropper/Cropper.js +115 -0
  54. package/Cropper/CropperElement.d.ts +10 -0
  55. package/Cropper/CropperElement.js +892 -0
  56. package/Cropper/index.d.ts +18 -0
  57. package/Cropper/index.js +8 -0
  58. package/Cropper/tools.d.ts +90 -0
  59. package/Cropper/tools.js +143 -0
  60. package/Cropper/typings.d.ts +69 -0
  61. package/Cropper/utils/cropper-calculations.d.ts +39 -0
  62. package/Cropper/utils/cropper-calculations.js +95 -0
  63. package/DateTimePicker/DateTimePicker.d.ts +1 -1
  64. package/DateTimePicker/DateTimePicker.js +14 -1
  65. package/Dropdown/Dropdown.d.ts +7 -1
  66. package/Dropdown/Dropdown.js +31 -14
  67. package/Dropdown/DropdownItem.d.ts +7 -1
  68. package/Dropdown/DropdownItem.js +36 -6
  69. package/Dropdown/DropdownItemCard.js +2 -1
  70. package/FloatingButton/FloatingButton.d.ts +21 -0
  71. package/FloatingButton/FloatingButton.js +18 -0
  72. package/FloatingButton/index.d.ts +2 -0
  73. package/FloatingButton/index.js +1 -0
  74. package/Form/FormField.d.ts +21 -10
  75. package/Form/FormField.js +12 -4
  76. package/Input/Input.js +9 -2
  77. package/Message/Message.js +1 -1
  78. package/MultipleDatePicker/MultipleDatePicker.js +2 -2
  79. package/Navigation/NavigationHeader.js +1 -1
  80. package/Picker/FormattedInput.d.ts +1 -1
  81. package/Picker/FormattedInput.js +2 -1
  82. package/Picker/PickerTriggerWithSeparator.d.ts +10 -0
  83. package/Picker/PickerTriggerWithSeparator.js +2 -2
  84. package/Picker/useDateInputFormatter.d.ts +6 -0
  85. package/Picker/useDateInputFormatter.js +4 -1
  86. package/Select/Select.d.ts +2 -8
  87. package/Select/Select.js +12 -33
  88. package/Select/SelectTrigger.js +21 -7
  89. package/Select/index.d.ts +0 -4
  90. package/Select/index.js +0 -2
  91. package/Select/typings.d.ts +0 -4
  92. package/Select/useSelectTriggerTags.d.ts +1 -1
  93. package/Select/useSelectTriggerTags.js +9 -6
  94. package/Separator/Separator.d.ts +14 -0
  95. package/Separator/Separator.js +17 -0
  96. package/Separator/index.d.ts +2 -0
  97. package/Separator/index.js +1 -0
  98. package/Table/utils/useTableRowSelection.js +6 -0
  99. package/Tag/TagGroup.d.ts +4 -2
  100. package/Tag/TagGroup.js +7 -4
  101. package/TextField/TextField.d.ts +1 -1
  102. package/TextField/TextField.js +63 -9
  103. package/TimePanel/TimePanelColumn.js +19 -12
  104. package/index.d.ts +27 -28
  105. package/index.js +23 -25
  106. package/package.json +4 -4
  107. package/Accordion/AccordionDetails.d.ts +0 -9
  108. package/Accordion/AccordionSummary.d.ts +0 -18
  109. package/Accordion/AccordionSummary.js +0 -51
  110. package/Alert/Alert.d.ts +0 -20
  111. package/Alert/Alert.js +0 -18
  112. package/Alert/index.d.ts +0 -3
  113. package/Alert/index.js +0 -1
  114. package/Card/Card.d.ts +0 -51
  115. package/Card/Card.js +0 -20
  116. package/Card/CardActions.d.ts +0 -34
  117. package/Card/CardActions.js +0 -15
  118. package/ConfirmActions/ConfirmActions.d.ts +0 -46
  119. package/ConfirmActions/ConfirmActions.js +0 -15
  120. package/ConfirmActions/index.d.ts +0 -2
  121. package/ConfirmActions/index.js +0 -1
  122. package/Select/Option.d.ts +0 -18
  123. package/Select/Option.js +0 -45
  124. package/Select/TreeSelect.d.ts +0 -72
  125. package/Select/TreeSelect.js +0 -205
  126. package/Tree/Tree.d.ts +0 -70
  127. package/Tree/Tree.js +0 -139
  128. package/Tree/TreeNode.d.ts +0 -40
  129. package/Tree/TreeNode.js +0 -50
  130. package/Tree/TreeNodeList.d.ts +0 -24
  131. package/Tree/TreeNodeList.js +0 -28
  132. package/Tree/getTreeNodeEntities.d.ts +0 -11
  133. package/Tree/getTreeNodeEntities.js +0 -92
  134. package/Tree/index.d.ts +0 -13
  135. package/Tree/index.js +0 -7
  136. package/Tree/toggleValue.d.ts +0 -4
  137. package/Tree/toggleValue.js +0 -19
  138. package/Tree/traverseTree.d.ts +0 -2
  139. package/Tree/traverseTree.js +0 -11
  140. package/Tree/typings.d.ts +0 -16
  141. package/Tree/useTreeExpandedValue.d.ts +0 -14
  142. package/Tree/useTreeExpandedValue.js +0 -33
@@ -15,6 +15,7 @@ import Dropdown from '../Dropdown/Dropdown.js';
15
15
  import cx from 'clsx';
16
16
 
17
17
  const MENU_ID_PREFIX = 'mzn-select-autocomplete-menu-id';
18
+ const BLUR_RESET_OPTIONS_DELAY = 120;
18
19
  /**
19
20
  * Type guard to check if value is array (multiple mode)
20
21
  */
@@ -46,7 +47,8 @@ function isOptionSelected(option, value, isMultiple) {
46
47
  */
47
48
  const AutoComplete = forwardRef(function AutoComplete(props, ref) {
48
49
  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, 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, globalPortal = true, onReachBottom, onLeaveBottom, } = props;
50
+ const { addable = false, asyncData = false, className, clearSearchText = true, createSeparators = [',', '+', '\n'], defaultValue, disabled = disabledFromFormControl || false, disabledOptionsFilter = false, emptyText, error = severity === 'error' || false, fullWidth = fullWidthFromFormControl || false, id, inputPosition = 'outside', inputProps, inputRef, loading = false, loadingText, loadingPosition = 'bottom', menuMaxHeight, mode = 'single', name, onClear: onClearProp, onChange: onChangeProp, onInsert, onSearch, onSearchTextChange, onVisibilityChange, open: openProp, options: optionsProp, overflowStrategy, placeholder = '', prefix, required = requiredFromFormControl || false, searchDebounceTime = 300, searchTextControlRef, size, trimOnCreate = true, value: valueProp, createActionText, createActionTextTemplate = '建立 "{text}"', dropdownZIndex, globalPortal = true, onReachBottom, onLeaveBottom, } = props;
51
+ const shouldClearSearchTextOnBlur = clearSearchText;
50
52
  const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
51
53
  const isMultiple = mode === 'multiple';
52
54
  const isSingle = !isMultiple;
@@ -142,20 +144,51 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
142
144
  return result;
143
145
  }, [clearNewlyCreated, isMultiple, isSingle, markUnselected, onChange, value]);
144
146
  const nodeRef = useRef(null);
147
+ const inputElementRef = useRef(null);
145
148
  const controlRef = useRef(null);
149
+ const resetOptionsTimeoutRef = useRef(null);
150
+ const skipNextMultipleCloseResetRef = useRef(false);
146
151
  const composedRef = useComposeRefs([ref, controlRef]);
152
+ const composedInputRef = useComposeRefs([inputRef, inputElementRef]);
153
+ const clearPendingOptionsReset = useCallback(() => {
154
+ if (resetOptionsTimeoutRef.current !== null) {
155
+ window.clearTimeout(resetOptionsTimeoutRef.current);
156
+ resetOptionsTimeoutRef.current = null;
157
+ }
158
+ }, []);
159
+ const clearSearchInputDisplay = useCallback(() => {
160
+ if (inputElementRef.current) {
161
+ inputElementRef.current.value = '';
162
+ }
163
+ }, []);
164
+ const resetSearchInputs = useCallback(() => {
165
+ resetCreationInputs();
166
+ clearSearchInputDisplay();
167
+ }, [clearSearchInputDisplay, resetCreationInputs]);
168
+ const resetSearchInputsAndOptions = useCallback(() => {
169
+ resetSearchInputs();
170
+ clearPendingOptionsReset();
171
+ cancelSearch();
172
+ resetOptionsTimeoutRef.current = window.setTimeout(() => {
173
+ runSearch('', { immediate: true });
174
+ resetOptionsTimeoutRef.current = null;
175
+ }, BLUR_RESET_OPTIONS_DELAY);
176
+ }, [cancelSearch, clearPendingOptionsReset, resetSearchInputs, runSearch]);
177
+ useEffect(() => () => {
178
+ clearPendingOptionsReset();
179
+ }, [clearPendingOptionsReset]);
147
180
  // In single mode, show searchText when focused, otherwise show selected value
148
181
  // In multiple mode, always return empty string to avoid displaying "0"
149
182
  const renderValue = useMemo(() => {
150
183
  if (isSingle
151
- && (focused || (keepSearchTextOnBlur && !value && searchText))) {
184
+ && (focused || (!shouldClearSearchTextOnBlur && !value && searchText))) {
152
185
  return () => searchText;
153
186
  }
154
187
  if (isMultiple) {
155
188
  return () => '';
156
189
  }
157
190
  return undefined;
158
- }, [focused, isMultiple, isSingle, keepSearchTextOnBlur, searchText, value]);
191
+ }, [focused, isMultiple, isSingle, searchText, shouldClearSearchTextOnBlur, value]);
159
192
  function getPlaceholder() {
160
193
  if (isSingle && focused && isSingleValue(value)) {
161
194
  return value.name;
@@ -164,6 +197,7 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
164
197
  }
165
198
  /** Trigger input props */
166
199
  const onSearchInputChange = (e) => {
200
+ clearPendingOptionsReset();
167
201
  const nextSearch = e.target.value;
168
202
  /** should sync both search input and value */
169
203
  setSearchText(nextSearch);
@@ -180,6 +214,8 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
180
214
  };
181
215
  const onSearchInputFocus = (e) => {
182
216
  var _a;
217
+ skipNextMultipleCloseResetRef.current = false;
218
+ clearPendingOptionsReset();
183
219
  // When inputPosition is inside, let Dropdown handle the focus event
184
220
  // Otherwise, stop propagation to prevent conflicts
185
221
  if (inputPosition !== 'inside') {
@@ -195,6 +231,9 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
195
231
  };
196
232
  const onSearchInputBlur = (e) => {
197
233
  var _a, _b, _c;
234
+ // In multiple mode while dropdown is open, defer clearing to visibility change.
235
+ // This prevents clearing on intermediate blur triggered by dropdown interactions.
236
+ const shouldDeferMultipleBlurReset = isMultiple && open;
198
237
  // When inputPosition is inside, we need special handling
199
238
  if (inputPosition === 'inside') {
200
239
  // When open is controlled, prevent default blur behavior to avoid conflicts
@@ -203,33 +242,33 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
203
242
  // Don't let Dropdown's onBlur close the dropdown when controlled
204
243
  // Only call onFocus(false) to update internal state
205
244
  onFocus(false);
206
- // Clear search text and insert text when blur if keepSearchTextOnBlur is false
207
- if (!keepSearchTextOnBlur) {
208
- resetCreationInputs();
245
+ // Clear search text and insert text when blur clear behavior is enabled
246
+ if (shouldClearSearchTextOnBlur && !shouldDeferMultipleBlurReset) {
247
+ resetSearchInputsAndOptions();
209
248
  }
210
249
  (_a = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onBlur) === null || _a === void 0 ? void 0 : _a.call(inputProps, e);
211
250
  return;
212
251
  }
213
252
  // For uncontrolled mode, let Dropdown handle it normally
214
253
  // 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();
254
+ // Clear search text and insert text when blur clear behavior is enabled
255
+ if (shouldClearSearchTextOnBlur && !shouldDeferMultipleBlurReset) {
256
+ resetSearchInputsAndOptions();
218
257
  }
219
258
  (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onBlur) === null || _b === void 0 ? void 0 : _b.call(inputProps, e);
220
259
  return;
221
260
  }
222
261
  onFocus(false);
223
- // Clear search text and insert text when blur if keepSearchTextOnBlur is false
224
- if (!keepSearchTextOnBlur) {
225
- resetCreationInputs();
262
+ // Clear search text and insert text when blur clear behavior is enabled
263
+ if (shouldClearSearchTextOnBlur && !shouldDeferMultipleBlurReset) {
264
+ resetSearchInputsAndOptions();
226
265
  }
227
266
  (_c = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onBlur) === null || _c === void 0 ? void 0 : _c.call(inputProps, e);
228
267
  };
229
268
  const handleClear = useCallback((e) => {
230
269
  onClear(e);
231
- resetCreationInputs();
232
- }, [onClear, resetCreationInputs]);
270
+ resetSearchInputs();
271
+ }, [onClear, resetSearchInputs]);
233
272
  const onClickSuffixActionIcon = () => {
234
273
  toggleOpen((prev) => !prev);
235
274
  };
@@ -270,15 +309,9 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
270
309
  }, [mode, value]);
271
310
  // Disable input when loading
272
311
  const isInputDisabled = disabled || isLoading;
273
- // For rendering: when loading, force options to empty to show loading status in Dropdown
274
- const dropdownOptionsForRender = useMemo(() => {
275
- if (isLoading)
276
- return [];
277
- return dropdownOptions;
278
- }, [isLoading, dropdownOptions]);
279
312
  const dropdownStatus = isLoading
280
313
  ? 'loading'
281
- : dropdownOptionsForRender.length === 0
314
+ : dropdownOptions.length === 0
282
315
  ? 'empty'
283
316
  : undefined;
284
317
  // Handle dropdown option selection
@@ -296,13 +329,24 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
296
329
  onFocus(false);
297
330
  }
298
331
  else {
332
+ skipNextMultipleCloseResetRef.current = true;
299
333
  wrappedOnChange(selectedValue);
334
+ // In multiple mode, keep current filter text after selecting an item.
335
+ // Search text is cleared only when blur/close actually leaves the scope.
300
336
  }
301
337
  }
302
- }, [mode, onFocus, options, setSearchText, setInsertText, toggleOpen, wrappedOnChange]);
338
+ }, [
339
+ mode,
340
+ onFocus,
341
+ options,
342
+ setSearchText,
343
+ setInsertText,
344
+ toggleOpen,
345
+ wrappedOnChange,
346
+ ]);
303
347
  // Active index for dropdown keyboard navigation
304
348
  const [activeIndex, setActiveIndex] = useState(null);
305
- const setListboxHasVisualFocus = useCallback(() => { }, []);
349
+ const setListboxHasVisualFocus = useCallback((_focus) => { }, []);
306
350
  // Reset activeIndex when options change
307
351
  useEffect(() => {
308
352
  if (!dropdownOptions.length) {
@@ -339,7 +383,7 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
339
383
  handleBulkCreate,
340
384
  handleDropdownSelect,
341
385
  inputPropsOnKeyDown: inputProps === null || inputProps === void 0 ? void 0 : inputProps.onKeyDown,
342
- inputRef,
386
+ inputRef: inputElementRef,
343
387
  mode,
344
388
  onFocus,
345
389
  open,
@@ -354,13 +398,59 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
354
398
  value,
355
399
  wrappedOnChange,
356
400
  });
401
+ const onSearchInputKeyDown = useCallback((e) => {
402
+ var _a, _b;
403
+ if (e.key === 'Escape') {
404
+ e.preventDefault();
405
+ e.stopPropagation();
406
+ toggleOpen(false);
407
+ setActiveIndex(null);
408
+ setListboxHasVisualFocus(false);
409
+ onFocus(false);
410
+ (_a = inputElementRef.current) === null || _a === void 0 ? void 0 : _a.blur();
411
+ (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onKeyDown) === null || _b === void 0 ? void 0 : _b.call(inputProps, e);
412
+ return;
413
+ }
414
+ handleInputKeyDown(e);
415
+ }, [
416
+ handleInputKeyDown,
417
+ inputProps,
418
+ onFocus,
419
+ setActiveIndex,
420
+ setListboxHasVisualFocus,
421
+ toggleOpen,
422
+ ]);
357
423
  // Handle visibility change from Dropdown to prevent flickering
358
424
  const handleVisibilityChange = useCallback((newOpen) => {
425
+ var _a;
359
426
  // Only update if state actually changed to prevent flickering
360
427
  if (newOpen !== open) {
361
428
  toggleOpen(newOpen);
362
429
  }
363
- }, [open, toggleOpen]);
430
+ // In multiple mode, blur/close can be driven by Dropdown visibility updates.
431
+ // Keep input text cleanup consistent even when native input blur is not triggered.
432
+ if (!newOpen && isMultiple && shouldClearSearchTextOnBlur) {
433
+ if (skipNextMultipleCloseResetRef.current) {
434
+ const menuElement = document.getElementById(menuId);
435
+ const activeElement = document.activeElement;
436
+ const activeWithinHost = !!(activeElement
437
+ && (((_a = nodeRef.current) === null || _a === void 0 ? void 0 : _a.contains(activeElement))
438
+ || (menuElement && menuElement.contains(activeElement))));
439
+ skipNextMultipleCloseResetRef.current = false;
440
+ if (activeWithinHost) {
441
+ return;
442
+ }
443
+ }
444
+ resetSearchInputsAndOptions();
445
+ }
446
+ }, [
447
+ isMultiple,
448
+ menuId,
449
+ open,
450
+ resetSearchInputsAndOptions,
451
+ shouldClearSearchTextOnBlur,
452
+ toggleOpen,
453
+ ]);
364
454
  const handlePasteWithFallback = useCallback((e) => {
365
455
  var _a;
366
456
  handlePaste(e);
@@ -388,7 +478,6 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
388
478
  const alreadySelected = isOptionSelected(matchingOption, value, isMultiple);
389
479
  if (!alreadySelected) {
390
480
  wrappedOnChange(matchingOption);
391
- resetCreationInputs();
392
481
  return true;
393
482
  }
394
483
  return false;
@@ -398,7 +487,6 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
398
487
  isSingle,
399
488
  onFocus,
400
489
  options,
401
- resetCreationInputs,
402
490
  setSearchText,
403
491
  setInsertText,
404
492
  toggleOpen,
@@ -416,7 +504,7 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
416
504
  onBlur: onSearchInputBlur,
417
505
  onChange: onSearchInputChange,
418
506
  onFocus: onSearchInputFocus,
419
- onKeyDown: handleInputKeyDown,
507
+ onKeyDown: onSearchInputKeyDown,
420
508
  onPaste: handlePasteWithFallback,
421
509
  readOnly: false,
422
510
  role: 'combobox',
@@ -429,9 +517,9 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
429
517
  ? (createActionText
430
518
  ? createActionText(insertText)
431
519
  : createActionTextTemplate.replace('{text}', insertText))
432
- : undefined, activeIndex: activeIndex, disabled: isInputDisabled, emptyText: emptyText, followText: searchText, inputPosition: inputPosition, isMatchInputValue: true, listboxId: menuId, loadingText: loadingText, maxHeight: menuMaxHeight, mode: mode, onActionCustom: shouldShowCreateAction
520
+ : undefined, activeIndex: activeIndex, disabled: isInputDisabled, emptyText: emptyText, followText: searchText, inputPosition: inputPosition, isMatchInputValue: true, listboxId: menuId, loadingText: loadingText, loadingPosition: loadingPosition, maxHeight: menuMaxHeight, mode: mode, onActionCustom: shouldShowCreateAction
433
521
  ? handleActionCustom
434
- : 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, globalPortal: globalPortal, 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: {
522
+ : undefined, onItemHover: setActiveIndex, onSelect: handleDropdownSelect, onVisibilityChange: handleVisibilityChange, open: open, options: dropdownOptions, placement: "bottom", sameWidth: true, showDropdownActions: shouldShowCreateAction, showActionShowTopBar: shouldShowCreateAction, status: dropdownStatus, type: "default", value: dropdownValue, zIndex: dropdownZIndex, globalPortal: globalPortal, onReachBottom: onReachBottom, onLeaveBottom: onLeaveBottom, children: jsx(SelectTrigger, { ref: composedRef, active: open, className: className, clearable: true, disabled: isInputDisabled, fullWidth: fullWidth, inputRef: composedInputRef, mode: mode, onTagClose: wrappedOnChange, onClear: handleClear, overflowStrategy: overflowStrategy, placeholder: getPlaceholder(), prefix: prefix, readOnly: false, required: required, type: error ? 'error' : 'default', inputProps: {
435
523
  ...resolvedInputProps,
436
524
  onClick: (e) => {
437
525
  var _a;
@@ -15,26 +15,22 @@ const Backdrop = forwardRef(function Backdrop(props, ref) {
15
15
  const { children, className, container, disableCloseOnBackdropClick = false, disablePortal, disableScrollLock = false, onBackdropClick, onClose, open = false, variant = 'dark', ...rest } = props;
16
16
  // Lock body scroll when backdrop is open
17
17
  useScrollLock({ enabled: open && !disableScrollLock });
18
- // When using custom container or disablePortal, overlay should be absolutely positioned
19
- // When using default Portal (to #mzn-portal-container), overlay uses relative positioning
20
- const applyAbsolutePosition = Boolean(disablePortal || container);
21
- return (jsx(Portal, { container: container, disablePortal: disablePortal, layer: "default", children: jsxs("div", { ...rest, ref: ref, "aria-hidden": !open, className: cx(backdropClasses.host, {
22
- [backdropClasses.hostAbsolute]: applyAbsolutePosition,
18
+ return (jsx(Portal, { container: container, disablePortal: disablePortal, layer: "default", children: jsx("div", { ...rest, ref: ref, "aria-hidden": !open, className: cx(backdropClasses.host, backdropClasses.hostAbsolute, {
23
19
  [backdropClasses.hostOpen]: open,
24
- }, className), role: "presentation", children: [jsx(Fade, { in: open, duration: {
25
- enter: MOTION_DURATION.fast,
26
- exit: MOTION_DURATION.fast,
27
- }, easing: {
28
- enter: MOTION_EASING.standard,
29
- exit: MOTION_EASING.standard,
30
- }, children: jsx("div", { "aria-hidden": "true", className: cx(backdropClasses.backdrop, backdropClasses.backdropVariant(variant)), onClick: (event) => {
31
- if (!disableCloseOnBackdropClick && onClose) {
32
- onClose();
33
- }
34
- if (onBackdropClick) {
35
- onBackdropClick(event);
36
- }
37
- } }) }), jsx("div", { className: backdropClasses.content, children: children })] }) }));
20
+ }, className), role: "presentation", children: jsxs("div", { className: backdropClasses.main, children: [jsx(Fade, { in: open, duration: {
21
+ enter: MOTION_DURATION.fast,
22
+ exit: MOTION_DURATION.fast,
23
+ }, easing: {
24
+ enter: MOTION_EASING.standard,
25
+ exit: MOTION_EASING.standard,
26
+ }, children: jsx("div", { "aria-hidden": "true", className: cx(backdropClasses.backdrop, backdropClasses.backdropVariant(variant)), onClick: (event) => {
27
+ if (!disableCloseOnBackdropClick && onClose) {
28
+ onClose();
29
+ }
30
+ if (onBackdropClick) {
31
+ onBackdropClick(event);
32
+ }
33
+ } }) }), jsx("div", { className: backdropClasses.content, children: children })] }) }) }));
38
34
  });
39
35
 
40
36
  export { Backdrop as default };
@@ -74,7 +74,7 @@ function CalendarDays(props) {
74
74
  ? (() => {
75
75
  var _a, _b;
76
76
  const annotation = renderAnnotations(date);
77
- return (jsx(Typography, { variant: "annotation", color: (_a = annotation === null || annotation === void 0 ? void 0 : annotation.color) !== null && _a !== void 0 ? _a : 'text-neutral', children: (_b = annotation === null || annotation === void 0 ? void 0 : annotation.value) !== null && _b !== void 0 ? _b : '' }));
77
+ return (jsx(Typography, { variant: "annotation", color: (_a = annotation === null || annotation === void 0 ? void 0 : annotation.color) !== null && _a !== void 0 ? _a : 'text-neutral', children: (_b = annotation === null || annotation === void 0 ? void 0 : annotation.value) !== null && _b !== void 0 ? _b : '--' }));
78
78
  })()
79
79
  : null] }) }, `${getMonth(date)}/${getDate(date)}`));
80
80
  }) }, `CALENDAR_DAYS/WEEK_OF/${index}`)))] }) }));
@@ -0,0 +1,11 @@
1
+ import { ComponentOverridableForwardRefComponentPropsFactory } from '../utils/jsx-types';
2
+ import { BaseCardComponent, BaseCardProps } from './typings';
3
+ export type BaseCardComponentProps<C extends BaseCardComponent = 'div'> = ComponentOverridableForwardRefComponentPropsFactory<BaseCardComponent, C, BaseCardProps>;
4
+ /**
5
+ * BaseCard is a versatile card component that can be used as a div, link, or custom component.
6
+ * It supports four types: default, action, overflow, and toggle, each with different header actions.
7
+ */
8
+ declare const BaseCard: import("react").ForwardRefExoticComponent<Omit<Omit<import("../utils/jsx-types").ComponentPropsWithoutKeyAndRef<"div">, "children" | "title" | "defaultChecked" | "className" | "disabled" | "type" | "checked" | "readOnly" | "options" | "description" | "actionName" | "actionVariant" | "onActionClick" | "onOptionSelect" | "onToggleChange" | "toggleSize" | "toggleLabel" | "toggleSupportingText"> & BaseCardProps, "component"> & {
9
+ component?: BaseCardComponent | undefined;
10
+ } & import("react").RefAttributes<HTMLDivElement>>;
11
+ export default BaseCard;
@@ -0,0 +1,48 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { forwardRef } from 'react';
4
+ import { cardClasses } from '@mezzanine-ui/core/card';
5
+ import { DotHorizontalIcon } from '@mezzanine-ui/icons';
6
+ import Button from '../Button/Button.js';
7
+ import Dropdown from '../Dropdown/Dropdown.js';
8
+ import Toggle from '../Toggle/Toggle.js';
9
+ import cx from 'clsx';
10
+
11
+ /**
12
+ * BaseCard is a versatile card component that can be used as a div, link, or custom component.
13
+ * It supports four types: default, action, overflow, and toggle, each with different header actions.
14
+ */
15
+ const BaseCard = forwardRef(function BaseCard(props, ref) {
16
+ const { children, className, component: Component = 'div', disabled = false, readOnly = false, title, description, type = 'default', ...rest } = props;
17
+ const hasHeaderContent = Boolean(title || description);
18
+ const renderHeaderAction = () => {
19
+ if (type === 'default') {
20
+ return null;
21
+ }
22
+ if (type === 'action') {
23
+ const { actionName, actionVariant = 'base-text-link', onActionClick, } = props;
24
+ return (jsx("div", { className: cardClasses.baseHeaderAction, children: jsx(Button, { disabled: disabled, onClick: (event) => {
25
+ event.stopPropagation();
26
+ onActionClick === null || onActionClick === void 0 ? void 0 : onActionClick(event);
27
+ }, size: "sub", variant: actionVariant, type: "button", children: actionName }) }));
28
+ }
29
+ if (type === 'overflow') {
30
+ const { options, onOptionSelect } = props;
31
+ return (jsx("div", { className: cardClasses.baseHeaderAction, children: jsx(Dropdown, { disabled: disabled, mode: "single", onSelect: onOptionSelect, options: options, globalPortal: false, children: jsx(Button, { disabled: disabled, icon: DotHorizontalIcon, iconType: "icon-only", size: "sub", variant: "base-text-link", type: "button" }) }) }));
32
+ }
33
+ if (type === 'toggle') {
34
+ const { checked, defaultChecked, onToggleChange, toggleSize, toggleLabel, toggleSupportingText, } = props;
35
+ return (jsx("div", { className: cardClasses.baseHeaderAction, children: jsx(Toggle, { checked: checked, defaultChecked: defaultChecked, disabled: disabled, label: toggleLabel, onChange: onToggleChange, size: toggleSize, supportingText: toggleSupportingText }) }));
36
+ }
37
+ return null;
38
+ };
39
+ // Filter out type-specific props before spreading to component
40
+ const { actionName: _actionName, actionVariant: _actionVariant, onActionClick: _onActionClick, options: _options, onOptionSelect: _onOptionSelect, checked: _checked, defaultChecked: _defaultChecked, onToggleChange: _onToggleChange, toggleSize: _toggleSize, toggleLabel: _toggleLabel, toggleSupportingText: _toggleSupportingText, type: _type, ...componentProps } = rest;
41
+ return (jsxs(Component, { ...componentProps, ref: ref, "aria-disabled": disabled || undefined, "aria-readonly": readOnly || undefined, className: cx(cardClasses.base, {
42
+ [cardClasses.baseDisabled]: disabled,
43
+ [cardClasses.baseReadOnly]: readOnly,
44
+ }, className), children: [hasHeaderContent && (jsxs("div", { className: cardClasses.baseHeader, children: [jsxs("div", { className: cardClasses.baseHeaderContentWrapper, children: [title && (jsx("span", { className: cardClasses.baseHeaderTitle, children: title })), description && (jsx("span", { className: cardClasses.baseHeaderDescription, children: description }))] }), renderHeaderAction()] })), jsx("div", { className: cardClasses.baseContent, children: children })] }));
45
+ });
46
+ BaseCard.displayName = 'BaseCard';
47
+
48
+ export { BaseCard as default };
@@ -0,0 +1,14 @@
1
+ import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
2
+ export interface BaseCardSkeletonProps extends Omit<NativeElementPropsWithoutKeyAndRef<'div'>, 'children'> {
3
+ /**
4
+ * Whether to show content skeleton
5
+ * @default true
6
+ */
7
+ showContent?: boolean;
8
+ }
9
+ /**
10
+ * Skeleton placeholder for BaseCard component.
11
+ * Renders a skeleton that mimics the BaseCard layout.
12
+ */
13
+ declare const BaseCardSkeleton: import("react").ForwardRefExoticComponent<BaseCardSkeletonProps & import("react").RefAttributes<HTMLDivElement>>;
14
+ export default BaseCardSkeleton;
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { forwardRef } from 'react';
4
+ import { cardClasses } from '@mezzanine-ui/core/card';
5
+ import Skeleton from '../Skeleton/Skeleton.js';
6
+ import cx from 'clsx';
7
+
8
+ /**
9
+ * Skeleton placeholder for BaseCard component.
10
+ * Renders a skeleton that mimics the BaseCard layout.
11
+ */
12
+ const BaseCardSkeleton = forwardRef(function BaseCardSkeleton(props, ref) {
13
+ const { className, showContent = true, ...rest } = props;
14
+ return (jsxs("div", { ...rest, ref: ref, className: cx(cardClasses.base, cardClasses.baseReadOnly, className), children: [jsx("div", { className: cardClasses.baseHeader, children: jsxs("div", { className: cardClasses.baseHeaderContentWrapper, children: [jsx(Skeleton, { height: 20, width: "60%" }), jsx(Skeleton, { height: 16, width: "40%" })] }) }), showContent && (jsxs("div", { className: cardClasses.baseContent, children: [jsx(Skeleton, { height: 16, width: "100%" }), jsx(Skeleton, { height: 16, style: { marginTop: 8 }, width: "80%" })] }))] }));
15
+ });
16
+ BaseCardSkeleton.displayName = 'BaseCardSkeleton';
17
+
18
+ export { BaseCardSkeleton as default };
@@ -0,0 +1,47 @@
1
+ import { ReactNode } from 'react';
2
+ /**
3
+ * Card type for loading skeleton
4
+ */
5
+ export type CardGroupLoadingType = 'base' | 'four-thumbnail' | 'quick-action' | 'single-thumbnail';
6
+ export interface CardGroupProps {
7
+ /**
8
+ * Custom class name
9
+ */
10
+ className?: string;
11
+ /**
12
+ * Card components to render in the group.
13
+ * Only accepts BaseCard, QuickActionCard, SingleThumbnailCard, and FourThumbnailCard as children.
14
+ */
15
+ children?: ReactNode;
16
+ /**
17
+ * Whether to show loading skeletons
18
+ * @default false
19
+ */
20
+ loading?: boolean;
21
+ /**
22
+ * Number of skeleton items to render when loading
23
+ * @default 3
24
+ */
25
+ loadingCount?: number;
26
+ /**
27
+ * Type of card skeleton to render when loading.
28
+ * Required when loading is true.
29
+ */
30
+ loadingType?: CardGroupLoadingType;
31
+ /**
32
+ * Width of each thumbnail skeleton when loadingType is 'single-thumbnail' or 'four-thumbnail'.
33
+ * @default 360
34
+ */
35
+ loadingThumbnailWidth?: number | string;
36
+ /**
37
+ * Aspect ratio of thumbnail skeletons when loadingType is 'single-thumbnail' or 'four-thumbnail'.
38
+ * For single-thumbnail, defaults to '16/9'. For four-thumbnail, defaults to '4/3'.
39
+ */
40
+ loadingThumbnailAspectRatio?: string;
41
+ }
42
+ /**
43
+ * CardGroup is a container for card components.
44
+ * It uses CSS Grid to layout cards in a horizontal row with consistent spacing.
45
+ */
46
+ declare const CardGroup: import("react").ForwardRefExoticComponent<CardGroupProps & import("react").RefAttributes<HTMLDivElement>>;
47
+ export default CardGroup;
@@ -0,0 +1,147 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { cardClasses } from '@mezzanine-ui/core/card';
4
+ import { forwardRef, Children, isValidElement } from 'react';
5
+ import BaseCard from './BaseCard.js';
6
+ import BaseCardSkeleton from './BaseCardSkeleton.js';
7
+ import FourThumbnailCard from './FourThumbnailCard.js';
8
+ import FourThumbnailCardSkeleton from './FourThumbnailCardSkeleton.js';
9
+ import QuickActionCard from './QuickActionCard.js';
10
+ import QuickActionCardSkeleton from './QuickActionCardSkeleton.js';
11
+ import SingleThumbnailCard from './SingleThumbnailCard.js';
12
+ import SingleThumbnailCardSkeleton from './SingleThumbnailCardSkeleton.js';
13
+ import cx from 'clsx';
14
+
15
+ // List of allowed child component types
16
+ const ALLOWED_CARD_TYPES = [
17
+ BaseCard,
18
+ FourThumbnailCard,
19
+ QuickActionCard,
20
+ SingleThumbnailCard,
21
+ ];
22
+ /**
23
+ * Get display name of a component for error messages
24
+ */
25
+ function getComponentDisplayName(child) {
26
+ const { type } = child;
27
+ if (typeof type === 'string') {
28
+ return type;
29
+ }
30
+ return (type.displayName ||
31
+ type.name ||
32
+ 'Unknown');
33
+ }
34
+ /**
35
+ * Detect the first valid card type from children
36
+ */
37
+ function getFirstCardType(children) {
38
+ let firstType = null;
39
+ Children.forEach(children, (child) => {
40
+ if (firstType !== null)
41
+ return;
42
+ if (!isValidElement(child))
43
+ return;
44
+ if (child.type === QuickActionCard) {
45
+ firstType = QuickActionCard;
46
+ }
47
+ else if (child.type === BaseCard) {
48
+ firstType = BaseCard;
49
+ }
50
+ else if (child.type === SingleThumbnailCard) {
51
+ firstType = SingleThumbnailCard;
52
+ }
53
+ else if (child.type === FourThumbnailCard) {
54
+ firstType = FourThumbnailCard;
55
+ }
56
+ });
57
+ return firstType;
58
+ }
59
+ /**
60
+ * Get the skeleton component based on loading type
61
+ */
62
+ function getSkeletonComponent(loadingType) {
63
+ switch (loadingType) {
64
+ case 'base':
65
+ return BaseCardSkeleton;
66
+ case 'four-thumbnail':
67
+ return FourThumbnailCardSkeleton;
68
+ case 'quick-action':
69
+ return QuickActionCardSkeleton;
70
+ case 'single-thumbnail':
71
+ return SingleThumbnailCardSkeleton;
72
+ default:
73
+ return BaseCardSkeleton;
74
+ }
75
+ }
76
+ /**
77
+ * Get the group class modifier based on loading type
78
+ */
79
+ function getGroupClassFromLoadingType(loadingType) {
80
+ switch (loadingType) {
81
+ case 'four-thumbnail':
82
+ return cardClasses.groupFourThumbnail;
83
+ case 'quick-action':
84
+ return cardClasses.groupQuickAction;
85
+ case 'single-thumbnail':
86
+ return cardClasses.groupSingleThumbnail;
87
+ default:
88
+ return undefined;
89
+ }
90
+ }
91
+ /**
92
+ * CardGroup is a container for card components.
93
+ * It uses CSS Grid to layout cards in a horizontal row with consistent spacing.
94
+ */
95
+ const CardGroup = forwardRef(function CardGroup(props, ref) {
96
+ const { className, children, loading = false, loadingCount = 3, loadingThumbnailAspectRatio, loadingThumbnailWidth, loadingType, } = props;
97
+ // Detect first card type to determine min-width class
98
+ const firstCardType = getFirstCardType(children);
99
+ // Validate children at runtime
100
+ const validChildren = Children.map(children, (child) => {
101
+ if (!isValidElement(child)) {
102
+ return child;
103
+ }
104
+ const isAllowedType = ALLOWED_CARD_TYPES.some((allowedType) => child.type === allowedType);
105
+ if (!isAllowedType) {
106
+ const displayName = getComponentDisplayName(child);
107
+ console.warn(`[CardGroup] Invalid child type: <${displayName}>. ` +
108
+ 'CardGroup only accepts Card components (BaseCard, FourThumbnailCard, QuickActionCard, SingleThumbnailCard) as children.');
109
+ return null;
110
+ }
111
+ return child;
112
+ });
113
+ // Render loading skeletons
114
+ const renderSkeletons = () => {
115
+ if (!loading || !loadingType) {
116
+ return null;
117
+ }
118
+ const SkeletonComponent = getSkeletonComponent(loadingType);
119
+ // Build props for thumbnail skeletons
120
+ const thumbnailSkeletonProps = loadingType === 'single-thumbnail' || loadingType === 'four-thumbnail'
121
+ ? {
122
+ ...(loadingThumbnailAspectRatio && {
123
+ thumbnailAspectRatio: loadingThumbnailAspectRatio,
124
+ }),
125
+ ...(loadingThumbnailWidth && {
126
+ thumbnailWidth: loadingThumbnailWidth,
127
+ }),
128
+ }
129
+ : undefined;
130
+ return Array.from({ length: loadingCount }, (_, index) => (jsx(SkeletonComponent, { ...thumbnailSkeletonProps }, `skeleton-${index}`)));
131
+ };
132
+ // Determine group class modifier
133
+ const groupClassModifier = loadingType && loading
134
+ ? getGroupClassFromLoadingType(loadingType)
135
+ : undefined;
136
+ return (jsxs("div", { ref: ref, className: cx(cardClasses.group, {
137
+ [cardClasses.groupFourThumbnail]: firstCardType === FourThumbnailCard ||
138
+ groupClassModifier === cardClasses.groupFourThumbnail,
139
+ [cardClasses.groupQuickAction]: firstCardType === QuickActionCard ||
140
+ groupClassModifier === cardClasses.groupQuickAction,
141
+ [cardClasses.groupSingleThumbnail]: firstCardType === SingleThumbnailCard ||
142
+ groupClassModifier === cardClasses.groupSingleThumbnail,
143
+ }, className), children: [validChildren, renderSkeletons()] }));
144
+ });
145
+ CardGroup.displayName = 'CardGroup';
146
+
147
+ export { CardGroup as default };