@mezzanine-ui/react 1.0.0-beta.2 → 1.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Anchor/Anchor.d.ts +51 -18
- package/Anchor/Anchor.js +15 -15
- package/Anchor/AnchorGroup.d.ts +34 -0
- package/Anchor/AnchorGroup.js +37 -0
- package/Anchor/AnchorItem.d.ts +30 -0
- package/Anchor/AnchorItem.js +65 -0
- package/Anchor/index.d.ts +2 -0
- package/Anchor/index.js +1 -0
- package/Anchor/utils.d.ts +13 -0
- package/Anchor/utils.js +95 -0
- package/AutoComplete/AutoComplete.d.ts +217 -0
- package/AutoComplete/AutoComplete.js +433 -0
- package/AutoComplete/index.d.ts +2 -0
- package/AutoComplete/index.js +1 -0
- package/AutoComplete/useAutoCompleteCreation.d.ts +33 -0
- package/AutoComplete/useAutoCompleteCreation.js +201 -0
- package/AutoComplete/useAutoCompleteKeyboard.d.ts +31 -0
- package/AutoComplete/useAutoCompleteKeyboard.js +149 -0
- package/AutoComplete/useAutoCompleteSearch.d.ts +16 -0
- package/AutoComplete/useAutoCompleteSearch.js +69 -0
- package/AutoComplete/useCreationTracker.d.ts +17 -0
- package/AutoComplete/useCreationTracker.js +47 -0
- package/Breadcrumb/Breadcrumb.js +16 -21
- package/Breadcrumb/BreadcrumbDropdown.d.ts +11 -0
- package/Breadcrumb/BreadcrumbDropdown.js +22 -0
- package/Breadcrumb/BreadcrumbItem.d.ts +2 -3
- package/Breadcrumb/BreadcrumbItem.js +13 -31
- package/Breadcrumb/BreadcrumbOverflowMenu.d.ts +7 -0
- package/Breadcrumb/BreadcrumbOverflowMenu.js +77 -0
- package/Breadcrumb/BreadcrumbOverflowMenuDropdown.d.ts +11 -0
- package/Breadcrumb/BreadcrumbOverflowMenuDropdown.js +21 -0
- package/Breadcrumb/BreadcrumbOverflowMenuItem.d.ts +3 -0
- package/Breadcrumb/BreadcrumbOverflowMenuItem.js +27 -0
- package/Breadcrumb/typings.d.ts +21 -39
- package/Button/Button.js +13 -11
- package/Button/index.d.ts +1 -1
- package/Button/typings.d.ts +27 -4
- package/Checkbox/index.d.ts +4 -5
- package/Checkbox/index.js +1 -5
- package/ContentHeader/ContentHeader.d.ts +160 -0
- package/ContentHeader/ContentHeader.js +54 -0
- package/ContentHeader/index.d.ts +2 -0
- package/ContentHeader/index.js +1 -0
- package/ContentHeader/utils.d.ts +23 -0
- package/ContentHeader/utils.js +215 -0
- package/Description/Description.d.ts +12 -22
- package/Description/Description.js +4 -24
- package/Dropdown/Dropdown.d.ts +46 -1
- package/Dropdown/Dropdown.js +99 -14
- package/Dropdown/DropdownAction.d.ts +1 -1
- package/Dropdown/DropdownAction.js +1 -4
- package/Dropdown/DropdownItem.d.ts +28 -1
- package/Dropdown/DropdownItem.js +56 -14
- package/Dropdown/DropdownItemCard.d.ts +2 -2
- package/Dropdown/DropdownItemCard.js +20 -16
- package/Dropdown/DropdownStatus.js +29 -0
- package/Dropdown/dropdownKeydownHandler.d.ts +2 -1
- package/Dropdown/dropdownKeydownHandler.js +73 -0
- package/Dropdown/highlightText.js +5 -1
- package/Dropdown/shortcutTextHandler.d.ts +24 -0
- package/Dropdown/shortcutTextHandler.js +171 -0
- package/Empty/Empty.js +2 -1
- package/Empty/icons/EmptyMainNotificationIcon.d.ts +4 -0
- package/Empty/icons/EmptyMainNotificationIcon.js +9 -0
- package/Empty/typings.d.ts +2 -2
- package/FilterArea/Filter.d.ts +32 -0
- package/FilterArea/Filter.js +23 -0
- package/FilterArea/FilterArea.d.ts +58 -0
- package/FilterArea/FilterArea.js +31 -0
- package/FilterArea/FilterLine.d.ts +11 -0
- package/FilterArea/FilterLine.js +13 -0
- package/FilterArea/index.d.ts +6 -0
- package/FilterArea/index.js +3 -0
- package/Form/FormField.js +3 -1
- package/Input/Input.d.ts +35 -7
- package/Input/Input.js +48 -14
- package/Input/index.d.ts +1 -1
- package/Modal/MediaPreviewModal.d.ts +54 -0
- package/Modal/MediaPreviewModal.js +158 -0
- package/Modal/Modal.d.ts +103 -11
- package/Modal/Modal.js +14 -9
- package/Modal/ModalBodyForVerification.d.ts +59 -0
- package/Modal/ModalBodyForVerification.js +99 -0
- package/Modal/ModalControl.d.ts +2 -2
- package/Modal/ModalControl.js +1 -1
- package/Modal/ModalFooter.d.ts +119 -1
- package/Modal/ModalFooter.js +15 -3
- package/Modal/ModalHeader.d.ts +26 -7
- package/Modal/ModalHeader.js +33 -7
- package/Modal/index.d.ts +6 -5
- package/Modal/index.js +2 -2
- package/Modal/useModalContainer.d.ts +12 -3
- package/Modal/useModalContainer.js +28 -6
- package/Navigation/Navigation.d.ts +7 -2
- package/Navigation/Navigation.js +36 -35
- package/Navigation/NavigationHeader.d.ts +4 -0
- package/Navigation/NavigationHeader.js +3 -2
- package/Navigation/NavigationOption.d.ts +8 -3
- package/Navigation/NavigationOption.js +46 -11
- package/Navigation/NavigationOptionCategory.js +1 -0
- package/Navigation/NavigationOverflowMenu.d.ts +6 -0
- package/Navigation/NavigationOverflowMenu.js +90 -0
- package/Navigation/NavigationOverflowMenuOption.d.ts +7 -0
- package/Navigation/NavigationOverflowMenuOption.js +68 -0
- package/Navigation/NavigationUserMenu.d.ts +4 -2
- package/Navigation/NavigationUserMenu.js +13 -5
- package/Navigation/context.d.ts +3 -2
- package/Navigation/useVisibleItems.d.ts +5 -0
- package/Navigation/useVisibleItems.js +54 -0
- package/NotificationCenter/NotificationCenter.d.ts +124 -0
- package/NotificationCenter/NotificationCenter.js +279 -0
- package/NotificationCenter/NotificationCenterDrawer.d.ts +109 -0
- package/NotificationCenter/index.d.ts +3 -0
- package/NotificationCenter/index.js +1 -0
- package/PageFooter/PageFooter.d.ts +19 -9
- package/PageFooter/PageFooter.js +10 -10
- package/PageHeader/PageHeader.d.ts +32 -25
- package/PageHeader/PageHeader.js +49 -43
- package/ResultState/ResultState.d.ts +9 -0
- package/ResultState/ResultState.js +36 -4
- package/Scrollbar/Scrollbar.d.ts +9 -0
- package/Scrollbar/Scrollbar.js +78 -0
- package/Scrollbar/index.d.ts +2 -0
- package/Scrollbar/index.js +1 -0
- package/Scrollbar/typings.d.ts +47 -0
- package/Select/SelectTrigger.js +5 -4
- package/Select/index.d.ts +0 -2
- package/Select/index.js +0 -1
- package/Select/typings.d.ts +6 -1
- package/Selection/Selection.js +1 -1
- package/Selection/SelectionGroup.d.ts +28 -0
- package/Slider/useSlider.js +1 -1
- package/Table/Table.d.ts +2 -120
- package/Table/Table.js +148 -53
- package/Table/TableContext.d.ts +11 -12
- package/Table/components/TableActionsCell.js +12 -4
- package/Table/components/TableBody.js +2 -1
- package/Table/components/TableBulkActions.js +1 -19
- package/Table/components/TableColGroup.d.ts +1 -4
- package/Table/components/TableColGroup.js +15 -16
- package/Table/components/TableCollectableCell.d.ts +17 -0
- package/Table/components/TableCollectableCell.js +54 -0
- package/Table/components/TableDragOrPinHandleCell.d.ts +20 -0
- package/Table/components/TableDragOrPinHandleCell.js +58 -0
- package/Table/components/TableExpandedRow.js +11 -2
- package/Table/components/TableHeader.js +12 -10
- package/Table/components/TableRow.js +38 -13
- package/Table/components/TableSelectionCell.js +1 -1
- package/Table/components/TableToggleableCell.d.ts +16 -0
- package/Table/components/TableToggleableCell.js +51 -0
- package/Table/components/index.d.ts +4 -1
- package/Table/components/index.js +3 -0
- package/Table/hooks/typings.d.ts +18 -4
- package/Table/hooks/useTableExpansion.d.ts +2 -2
- package/Table/hooks/useTableExpansion.js +5 -5
- package/Table/hooks/useTableFixedOffsets.d.ts +6 -2
- package/Table/hooks/useTableFixedOffsets.js +60 -26
- package/Table/hooks/useTableScroll.d.ts +9 -3
- package/Table/hooks/useTableScroll.js +34 -7
- package/Table/hooks/useTableVirtualization.d.ts +2 -1
- package/Table/hooks/useTableVirtualization.js +2 -8
- package/Table/index.d.ts +4 -3
- package/Table/index.js +3 -0
- package/Table/typings.d.ts +172 -0
- package/Table/utils/useTableRowSelection.js +13 -5
- package/Tag/TagGroup.d.ts +3 -0
- package/Tag/index.d.ts +2 -0
- package/Tag/index.js +1 -0
- package/Transition/Slide.d.ts +9 -2
- package/Transition/Slide.js +7 -4
- package/Tree/TreeNode.js +1 -1
- package/Upload/UploadPictureCard.js +1 -1
- package/index.d.ts +37 -21
- package/index.js +25 -11
- package/package.json +6 -4
- package/Modal/ModalActions.d.ts +0 -9
- package/Modal/ModalActions.js +0 -20
- package/Modal/ModalBody.d.ts +0 -7
- package/Modal/ModalBody.js +0 -14
- package/Notification/Notification.d.ts +0 -54
- package/Notification/Notification.js +0 -76
- package/Notification/index.d.ts +0 -3
- package/Notification/index.js +0 -1
- package/PageToolbar/PageToolbar.d.ts +0 -114
- package/PageToolbar/PageToolbar.js +0 -23
- package/PageToolbar/index.d.ts +0 -2
- package/PageToolbar/index.js +0 -1
- package/PageToolbar/utils.d.ts +0 -23
- package/PageToolbar/utils.js +0 -165
- package/Select/AutoComplete.d.ts +0 -107
- package/Select/AutoComplete.js +0 -114
- package/Table/components/TableDragHandleCell.d.ts +0 -11
- package/Table/components/TableDragHandleCell.js +0 -44
package/Dropdown/DropdownItem.js
CHANGED
|
@@ -8,6 +8,8 @@ import { useElementHeight } from '../hooks/useElementHeight.js';
|
|
|
8
8
|
import Typography from '../Typography/Typography.js';
|
|
9
9
|
import DropdownAction from './DropdownAction.js';
|
|
10
10
|
import DropdownItemCard from './DropdownItemCard.js';
|
|
11
|
+
import DropdownStatus from './DropdownStatus.js';
|
|
12
|
+
import { shortcutTextHandler } from './shortcutTextHandler.js';
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* Limits DropdownOption array to a maximum depth, truncating extra children levels and showing error message if exceeded.
|
|
@@ -55,9 +57,10 @@ function truncateArrayDepth(input, maxDepth = 3, warn = true) {
|
|
|
55
57
|
return truncate(input);
|
|
56
58
|
}
|
|
57
59
|
function DropdownItem(props) {
|
|
58
|
-
const { activeIndex, disabled = false, listboxId, listboxLabel, mode = 'single', options, value, type, maxHeight, actionConfig, onHover, onSelect, followText, headerContent, } = props;
|
|
60
|
+
const { activeIndex, disabled = false, listboxId, listboxLabel, mode = 'single', options, value, type, maxHeight, actionConfig, onHover, onSelect, followText, headerContent, status, loadingText, emptyText, emptyIcon, onReachBottom, onLeaveBottom, } = props;
|
|
59
61
|
const optionsContent = truncateArrayDepth(options, 3);
|
|
60
62
|
const listRef = useRef(null);
|
|
63
|
+
const listWrapperRef = useRef(null);
|
|
61
64
|
const [expandedNodes, setExpandedNodes] = useState(new Set());
|
|
62
65
|
const hasActions = Boolean(actionConfig === null || actionConfig === void 0 ? void 0 : actionConfig.showActions);
|
|
63
66
|
const hasHeader = Boolean(headerContent);
|
|
@@ -176,18 +179,21 @@ function DropdownItem(props) {
|
|
|
176
179
|
if (hasChildren) {
|
|
177
180
|
groupElements.push(jsx(Typography, { variant: "body", className: dropdownClasses.groupLabel, children: groupOption.name }, groupOption.id));
|
|
178
181
|
(_a = groupOption.children) === null || _a === void 0 ? void 0 : _a.forEach((option) => {
|
|
179
|
-
var _a, _b;
|
|
182
|
+
var _a, _b, _c;
|
|
180
183
|
currentIndex += 1;
|
|
181
184
|
const optionIndex = currentIndex;
|
|
182
185
|
const isActive = optionIndex === activeIndex;
|
|
183
186
|
const isSelected = Array.isArray(value)
|
|
184
187
|
? value.includes(option.id)
|
|
185
188
|
: value === option.id;
|
|
189
|
+
const shortcutText = option.shortcutText
|
|
190
|
+
? option.shortcutText
|
|
191
|
+
: shortcutTextHandler((_a = option.shortcutKeys) !== null && _a !== void 0 ? _a : []);
|
|
186
192
|
groupElements.push(jsx(DropdownItemCard, { followText: followText, active: isActive, checked: isSelected, disabled: disabled, id: `${listboxId}-option-${optionIndex}`, label: option.name, mode: mode, name: option.name, onClick: () => {
|
|
187
193
|
if (disabled)
|
|
188
194
|
return;
|
|
189
195
|
onSelect === null || onSelect === void 0 ? void 0 : onSelect(option);
|
|
190
|
-
}, checkSite: "none", validate: (
|
|
196
|
+
}, checkSite: "none", validate: (_b = option.validate) !== null && _b !== void 0 ? _b : 'default', onMouseEnter: () => onHover === null || onHover === void 0 ? void 0 : onHover(optionIndex), showUnderline: (_c = option.showUnderline) !== null && _c !== void 0 ? _c : false, appendContent: shortcutText }, option.id));
|
|
191
197
|
});
|
|
192
198
|
}
|
|
193
199
|
return groupElements;
|
|
@@ -197,7 +203,7 @@ function DropdownItem(props) {
|
|
|
197
203
|
const renderTreeOptions = (optionList, depth, startIndex) => {
|
|
198
204
|
let currentIndex = startIndex;
|
|
199
205
|
const elements = (optionList !== null && optionList !== void 0 ? optionList : []).flatMap((option) => {
|
|
200
|
-
var _a, _b;
|
|
206
|
+
var _a, _b, _c;
|
|
201
207
|
currentIndex += 1;
|
|
202
208
|
const optionIndex = currentIndex;
|
|
203
209
|
const level = Math.min(depth, 2);
|
|
@@ -211,7 +217,10 @@ function DropdownItem(props) {
|
|
|
211
217
|
if (hasChildren && level !== 2) {
|
|
212
218
|
prependIcon = isExpanded ? CaretDownIcon : CaretRightIcon;
|
|
213
219
|
}
|
|
214
|
-
const checkSite = option.showCheckbox ? '
|
|
220
|
+
const checkSite = option.showCheckbox ? 'prefix' : 'none';
|
|
221
|
+
const shortcutText = option.shortcutText
|
|
222
|
+
? option.shortcutText
|
|
223
|
+
: shortcutTextHandler((_a = option.shortcutKeys) !== null && _a !== void 0 ? _a : []);
|
|
215
224
|
const card = (jsx(DropdownItemCard, { active: isActive, checked: isSelected, disabled: disabled, id: `${listboxId}-option-${optionIndex}`, label: option.name, level: level, mode: mode, name: option.name, onClick: () => {
|
|
216
225
|
if (disabled)
|
|
217
226
|
return;
|
|
@@ -221,7 +230,7 @@ function DropdownItem(props) {
|
|
|
221
230
|
else {
|
|
222
231
|
onSelect === null || onSelect === void 0 ? void 0 : onSelect(option);
|
|
223
232
|
}
|
|
224
|
-
}, followText: followText, checkSite: checkSite, onMouseEnter: () => onHover === null || onHover === void 0 ? void 0 : onHover(optionIndex), prependIcon: prependIcon, showUnderline: (
|
|
233
|
+
}, followText: followText, checkSite: checkSite, onMouseEnter: () => onHover === null || onHover === void 0 ? void 0 : onHover(optionIndex), prependIcon: prependIcon, showUnderline: (_b = option.showUnderline) !== null && _b !== void 0 ? _b : false, validate: (_c = option.validate) !== null && _c !== void 0 ? _c : 'default', appendContent: shortcutText }, option.id));
|
|
225
234
|
if (hasChildren && isExpanded && type === 'tree') {
|
|
226
235
|
const childResult = renderTreeOptions(option.children, depth + 1, currentIndex);
|
|
227
236
|
currentIndex = childResult.nextIndex;
|
|
@@ -234,22 +243,22 @@ function DropdownItem(props) {
|
|
|
234
243
|
const renderDefaultOptions = (optionList, startIndex) => {
|
|
235
244
|
let currentIndex = startIndex;
|
|
236
245
|
const elements = (optionList !== null && optionList !== void 0 ? optionList : []).flatMap((option) => {
|
|
237
|
-
var _a, _b;
|
|
246
|
+
var _a, _b, _c, _d;
|
|
238
247
|
currentIndex += 1;
|
|
239
248
|
const optionIndex = currentIndex;
|
|
240
249
|
const isSelected = Array.isArray(value)
|
|
241
250
|
? value.includes(option.id)
|
|
242
251
|
: value === option.id;
|
|
243
252
|
const isActive = optionIndex === activeIndex;
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
253
|
+
const shortcutText = option.shortcutText
|
|
254
|
+
? option.shortcutText
|
|
255
|
+
: shortcutTextHandler((_a = option.shortcutKeys) !== null && _a !== void 0 ? _a : []);
|
|
256
|
+
const checkSite = (_b = option === null || option === void 0 ? void 0 : option.checkSite) !== null && _b !== void 0 ? _b : 'none';
|
|
248
257
|
return (jsx(DropdownItemCard, { followText: followText, active: isActive, checked: isSelected, disabled: disabled, id: `${listboxId}-option-${optionIndex}`, label: option.name, mode: mode, name: option.name, onClick: () => {
|
|
249
258
|
if (disabled)
|
|
250
259
|
return;
|
|
251
260
|
onSelect === null || onSelect === void 0 ? void 0 : onSelect(option);
|
|
252
|
-
}, onMouseEnter: () => onHover === null || onHover === void 0 ? void 0 : onHover(optionIndex), prependIcon: option.icon, validate: (
|
|
261
|
+
}, onMouseEnter: () => onHover === null || onHover === void 0 ? void 0 : onHover(optionIndex), prependIcon: option.icon, validate: (_c = option.validate) !== null && _c !== void 0 ? _c : 'default', showUnderline: (_d = option.showUnderline) !== null && _d !== void 0 ? _d : false, checkSite: checkSite, appendContent: shortcutText }, option.id));
|
|
253
262
|
});
|
|
254
263
|
return { elements, nextIndex: currentIndex };
|
|
255
264
|
};
|
|
@@ -263,6 +272,8 @@ function DropdownItem(props) {
|
|
|
263
272
|
return renderDefaultOptions(optionList, startIndex);
|
|
264
273
|
};
|
|
265
274
|
const { elements: renderedOptions } = renderOptions(optionsContent, 0, -1);
|
|
275
|
+
// Show status when options are empty and status is provided
|
|
276
|
+
const shouldShowStatus = optionsContent.length === 0 && status;
|
|
266
277
|
const listStyle = useMemo(() => {
|
|
267
278
|
if (!maxHeight) {
|
|
268
279
|
return undefined;
|
|
@@ -310,9 +321,40 @@ function DropdownItem(props) {
|
|
|
310
321
|
listElement.removeEventListener('keydown', handleKeyDown);
|
|
311
322
|
};
|
|
312
323
|
}, [disabled, matchShortcut, onSelect, type, toggleExpand, visibleShortcutOptions]);
|
|
324
|
+
// Handle scroll to bottom detection
|
|
325
|
+
useEffect(() => {
|
|
326
|
+
const listWrapperElement = listWrapperRef.current;
|
|
327
|
+
if (!listWrapperElement || !maxHeight || (!onReachBottom && !onLeaveBottom)) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
// Initialize wasAtBottom state by checking current position
|
|
331
|
+
const checkInitialState = () => {
|
|
332
|
+
const { scrollTop, scrollHeight, clientHeight } = listWrapperElement;
|
|
333
|
+
return scrollTop + clientHeight >= scrollHeight - 1;
|
|
334
|
+
};
|
|
335
|
+
let wasAtBottom = checkInitialState();
|
|
336
|
+
const handleScroll = () => {
|
|
337
|
+
const { scrollTop, scrollHeight, clientHeight } = listWrapperElement;
|
|
338
|
+
// Check if scrolled to bottom (with 1px threshold for rounding errors)
|
|
339
|
+
const isAtBottom = scrollTop + clientHeight >= scrollHeight - 1;
|
|
340
|
+
// Trigger onReachBottom when entering bottom state
|
|
341
|
+
if (isAtBottom && !wasAtBottom) {
|
|
342
|
+
onReachBottom === null || onReachBottom === void 0 ? void 0 : onReachBottom();
|
|
343
|
+
}
|
|
344
|
+
// Trigger onLeaveBottom when leaving bottom state
|
|
345
|
+
if (!isAtBottom && wasAtBottom) {
|
|
346
|
+
onLeaveBottom === null || onLeaveBottom === void 0 ? void 0 : onLeaveBottom();
|
|
347
|
+
}
|
|
348
|
+
wasAtBottom = isAtBottom;
|
|
349
|
+
};
|
|
350
|
+
listWrapperElement.addEventListener('scroll', handleScroll);
|
|
351
|
+
return () => {
|
|
352
|
+
listWrapperElement.removeEventListener('scroll', handleScroll);
|
|
353
|
+
};
|
|
354
|
+
}, [maxHeight, onReachBottom, onLeaveBottom]);
|
|
313
355
|
return (jsxs("ul", { "aria-label": listboxLabel || (optionsContent.length === 0 ? 'Dropdown options' : undefined), className: dropdownClasses.list, id: listboxId, ref: listRef, role: "listbox", style: listStyle, tabIndex: -1, children: [hasHeader && (jsx("li", { className: dropdownClasses.listHeader, role: "presentation", ref: headerRef, children: jsx("div", { className: dropdownClasses.listHeaderInner, children: headerContent }) })), maxHeight
|
|
314
|
-
? (jsx("div", { className: dropdownClasses.listWrapper, style: listWrapperStyle, children: renderedOptions }))
|
|
315
|
-
: renderedOptions, hasActions && (jsx("div", { ref: actionRef, children: jsx(DropdownAction, { ...actionConfig }) }))] }));
|
|
356
|
+
? (jsx("div", { ref: listWrapperRef, className: dropdownClasses.listWrapper, style: listWrapperStyle, children: shouldShowStatus ? (jsx(DropdownStatus, { status: status, loadingText: loadingText, emptyText: emptyText, emptyIcon: emptyIcon })) : (renderedOptions) }))
|
|
357
|
+
: shouldShowStatus ? (jsx(DropdownStatus, { status: status, loadingText: loadingText, emptyText: emptyText, emptyIcon: emptyIcon })) : (renderedOptions), hasActions && (jsx("div", { ref: actionRef, children: jsx(DropdownAction, { ...actionConfig }) }))] }));
|
|
316
358
|
}
|
|
317
359
|
|
|
318
360
|
export { DropdownItem as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DropdownCheckPosition, DropdownItemLevel, DropdownItemValidate, DropdownMode } from
|
|
2
|
-
import { type IconDefinition } from
|
|
1
|
+
import { DropdownCheckPosition, DropdownItemLevel, DropdownItemValidate, DropdownMode } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
2
|
+
import { type IconDefinition } from '@mezzanine-ui/icons';
|
|
3
3
|
export interface DropdownItemCardProps {
|
|
4
4
|
/**
|
|
5
5
|
* Whether the option is currently active (highlighted by keyboard navigation).
|
|
@@ -4,10 +4,10 @@ import cx from 'clsx';
|
|
|
4
4
|
import { useMemo, useState } from 'react';
|
|
5
5
|
import { dropdownClasses } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
6
6
|
import { CheckedIcon } from '@mezzanine-ui/icons';
|
|
7
|
-
import Checkbox from '../Checkbox/Checkbox.js';
|
|
8
7
|
import Typography from '../Typography/Typography.js';
|
|
9
8
|
import { highlightText } from './highlightText.js';
|
|
10
9
|
import Icon from '../Icon/Icon.js';
|
|
10
|
+
import Checkbox from '../Checkbox/Checkbox.js';
|
|
11
11
|
|
|
12
12
|
function DropdownItemCard(props) {
|
|
13
13
|
const { active = false, appendIcon, appendContent, followText, id, label, level: levelProp, mode, name: _name, prependIcon, subTitle, validate, disabled, checked, defaultChecked, checkSite, onCheckedChange, onClick, className, onMouseEnter, showUnderline, } = props;
|
|
@@ -33,11 +33,12 @@ function DropdownItemCard(props) {
|
|
|
33
33
|
const isControlled = checked !== undefined;
|
|
34
34
|
const [internalChecked, setInternalChecked] = useState(defaultChecked !== null && defaultChecked !== void 0 ? defaultChecked : false);
|
|
35
35
|
const isChecked = isControlled ? checked : internalChecked;
|
|
36
|
-
const labelColor = useMemo(() => {
|
|
37
|
-
return validate === 'danger' ? 'text-error' : 'text-neutral-solid';
|
|
38
|
-
}, [validate]);
|
|
39
36
|
const appendIconColor = useMemo(() => {
|
|
40
|
-
|
|
37
|
+
if (disabled)
|
|
38
|
+
return 'neutral-light';
|
|
39
|
+
if (validate === 'danger')
|
|
40
|
+
return 'error';
|
|
41
|
+
return 'brand';
|
|
41
42
|
}, [disabled, validate]);
|
|
42
43
|
const iconColor = useMemo(() => {
|
|
43
44
|
if (disabled)
|
|
@@ -50,15 +51,15 @@ function DropdownItemCard(props) {
|
|
|
50
51
|
: [
|
|
51
52
|
{
|
|
52
53
|
text: cardLabel,
|
|
53
|
-
highlight: false
|
|
54
|
-
}
|
|
54
|
+
highlight: false,
|
|
55
|
+
},
|
|
55
56
|
];
|
|
56
57
|
}, [cardLabel, followText]);
|
|
57
58
|
const showPrependContent = useMemo(() => {
|
|
58
|
-
return prependIcon || (checkSite === '
|
|
59
|
+
return prependIcon || (checkSite === 'prefix' && mode === 'multiple');
|
|
59
60
|
}, [prependIcon, checkSite, mode]);
|
|
60
61
|
const showAppendContent = useMemo(() => {
|
|
61
|
-
return appendContent || appendIcon || (checkSite === '
|
|
62
|
+
return appendContent || appendIcon || (checkSite === 'suffix' && isChecked);
|
|
62
63
|
}, [appendContent, appendIcon, checkSite, isChecked]);
|
|
63
64
|
const subTitleParts = useMemo(() => {
|
|
64
65
|
return followText && subTitle
|
|
@@ -67,13 +68,15 @@ function DropdownItemCard(props) {
|
|
|
67
68
|
? [
|
|
68
69
|
{
|
|
69
70
|
text: subTitle,
|
|
70
|
-
highlight: false
|
|
71
|
-
}
|
|
71
|
+
highlight: false,
|
|
72
|
+
},
|
|
72
73
|
]
|
|
73
74
|
: [];
|
|
74
75
|
}, [subTitle, followText]);
|
|
75
|
-
const renderHighlightedText = (parts,
|
|
76
|
-
return (jsx(Typography, {
|
|
76
|
+
const renderHighlightedText = (parts, className, id) => {
|
|
77
|
+
return (jsx(Typography, { className: className, id: id, children: parts.map((part, index) => (jsx("span", { className: part.highlight && validate !== 'danger'
|
|
78
|
+
? dropdownClasses.cardHighlightedText
|
|
79
|
+
: '', children: part.text }, index))) }));
|
|
77
80
|
};
|
|
78
81
|
const toggleChecked = () => {
|
|
79
82
|
if (disabled)
|
|
@@ -105,11 +108,12 @@ function DropdownItemCard(props) {
|
|
|
105
108
|
}
|
|
106
109
|
};
|
|
107
110
|
return (jsxs(Fragment, { children: [jsx("li", { ...(labelId ? { 'aria-labelledby': labelId } : {}), ...(ariaLabel ? { 'aria-label': ariaLabel } : {}), "aria-selected": active, className: cx(dropdownClasses.card, dropdownClasses.cardLevel(level), {
|
|
108
|
-
// Highlight: keyboard/mouse focused (active) or selected (isChecked)
|
|
109
111
|
[dropdownClasses.cardActive]: active || isChecked,
|
|
110
112
|
[dropdownClasses.cardDisabled]: disabled,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
+
[dropdownClasses.cardDanger]: validate === 'danger',
|
|
114
|
+
}, className), id: id, role: "option", tabIndex: -1, onMouseEnter: onMouseEnter, onClick: handleClick, onKeyDown: handleKeyDown, children: jsxs("div", { className: dropdownClasses.cardContainer, children: [showPrependContent && (jsxs("div", { className: dropdownClasses.cardPrependContent, children: [prependIcon && jsx(Icon, { icon: prependIcon, color: iconColor }), checkSite === 'prefix' && mode === 'multiple' && (jsx(Checkbox, { checked: isChecked, disabled: disabled, onChange: handleCheckboxChange }))] })), jsxs("div", { className: dropdownClasses.cardBody, children: [cardLabel &&
|
|
115
|
+
renderHighlightedText(labelParts, dropdownClasses.cardTitle, labelId), subTitleParts.length > 0 &&
|
|
116
|
+
renderHighlightedText(subTitleParts, dropdownClasses.cardDescription)] }), showAppendContent && (jsxs("div", { className: dropdownClasses.cardAppendContent, children: [appendContent && (jsx(Typography, { color: "text-neutral-light", children: appendContent })), appendIcon && jsx(Icon, { icon: appendIcon, color: iconColor }), checkSite === 'suffix' && isChecked && (jsx(Icon, { icon: CheckedIcon, color: appendIconColor, size: 16 }))] }))] }) }), showUnderline && jsx("div", { className: dropdownClasses.cardUnderline })] }));
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
export { DropdownItemCard as default };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { dropdownClasses } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
5
|
+
import { SpinnerIcon, FolderOpenIcon } from '@mezzanine-ui/icons';
|
|
6
|
+
import Typography from '../Typography/Typography.js';
|
|
7
|
+
import Icon from '../Icon/Icon.js';
|
|
8
|
+
|
|
9
|
+
function DropdownStatus(props) {
|
|
10
|
+
const { status, loadingText, emptyText, emptyIcon } = props;
|
|
11
|
+
const defaultStatusText = useMemo(() => {
|
|
12
|
+
if (status === 'loading') {
|
|
13
|
+
return loadingText !== null && loadingText !== void 0 ? loadingText : 'Loading...';
|
|
14
|
+
}
|
|
15
|
+
if (status === 'empty') {
|
|
16
|
+
return emptyText !== null && emptyText !== void 0 ? emptyText : 'No matching options.';
|
|
17
|
+
}
|
|
18
|
+
return '';
|
|
19
|
+
}, [status, loadingText, emptyText]);
|
|
20
|
+
const IconElement = useMemo(() => {
|
|
21
|
+
if (status === 'loading') {
|
|
22
|
+
return jsx(Icon, { icon: SpinnerIcon, size: 16, spin: true, color: "brand" });
|
|
23
|
+
}
|
|
24
|
+
return jsx(Icon, { icon: emptyIcon !== null && emptyIcon !== void 0 ? emptyIcon : FolderOpenIcon, size: 16 });
|
|
25
|
+
}, [status, emptyIcon]);
|
|
26
|
+
return (jsxs("div", { className: dropdownClasses.status, children: [IconElement, jsx(Typography, { className: dropdownClasses.statusText, children: defaultStatusText })] }));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { DropdownStatus as default };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DropdownOption } from '@mezzanine-ui/core/dropdown/dropdown';
|
|
2
|
+
import { Dispatch, SetStateAction } from 'react';
|
|
2
3
|
/**
|
|
3
4
|
* Provides a keyboard navigation handler for dropdown lists, encapsulating Arrow keys, Enter, and Escape behaviors.
|
|
4
5
|
* Keeps logic centralized in DropdownItem for easy reuse.
|
|
@@ -9,7 +10,7 @@ export declare function createDropdownKeydownHandler(params: {
|
|
|
9
10
|
onEscape?: () => void;
|
|
10
11
|
open: boolean;
|
|
11
12
|
options: DropdownOption[];
|
|
12
|
-
setActiveIndex:
|
|
13
|
+
setActiveIndex: Dispatch<SetStateAction<number | null>>;
|
|
13
14
|
setListboxHasVisualFocus: (focus: boolean) => void;
|
|
14
15
|
setOpen: (open: boolean) => void;
|
|
15
16
|
}): (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides a keyboard navigation handler for dropdown lists, encapsulating Arrow keys, Enter, and Escape behaviors.
|
|
3
|
+
* Keeps logic centralized in DropdownItem for easy reuse.
|
|
4
|
+
*/
|
|
5
|
+
function createDropdownKeydownHandler(params) {
|
|
6
|
+
const { activeIndex, onEnterSelect, onEscape, open, options, setActiveIndex, setListboxHasVisualFocus, setOpen, } = params;
|
|
7
|
+
return (e) => {
|
|
8
|
+
if (options.length === 0)
|
|
9
|
+
return;
|
|
10
|
+
switch (e.key) {
|
|
11
|
+
case 'ArrowDown': {
|
|
12
|
+
e.preventDefault();
|
|
13
|
+
e.stopPropagation();
|
|
14
|
+
if (!open) {
|
|
15
|
+
setOpen(true);
|
|
16
|
+
setListboxHasVisualFocus(true);
|
|
17
|
+
setActiveIndex(() => 0);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
setListboxHasVisualFocus(true);
|
|
21
|
+
setActiveIndex((prev) => {
|
|
22
|
+
if (prev === null)
|
|
23
|
+
return 0;
|
|
24
|
+
return prev >= options.length - 1 ? 0 : prev + 1;
|
|
25
|
+
});
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case 'ArrowUp': {
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
e.stopPropagation();
|
|
31
|
+
if (!open) {
|
|
32
|
+
setOpen(true);
|
|
33
|
+
setListboxHasVisualFocus(true);
|
|
34
|
+
setActiveIndex(() => options.length - 1);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
setListboxHasVisualFocus(true);
|
|
38
|
+
setActiveIndex((prev) => {
|
|
39
|
+
if (prev === null)
|
|
40
|
+
return options.length - 1;
|
|
41
|
+
return prev <= 0 ? options.length - 1 : prev - 1;
|
|
42
|
+
});
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case 'Enter': {
|
|
46
|
+
if (!open)
|
|
47
|
+
return;
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
e.stopPropagation();
|
|
50
|
+
if (activeIndex !== null && options[activeIndex]) {
|
|
51
|
+
onEnterSelect === null || onEnterSelect === void 0 ? void 0 : onEnterSelect(options[activeIndex]);
|
|
52
|
+
}
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
case 'Escape': {
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
e.stopPropagation();
|
|
58
|
+
onEscape === null || onEscape === void 0 ? void 0 : onEscape();
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case 'Home':
|
|
62
|
+
case 'End':
|
|
63
|
+
case 'ArrowLeft':
|
|
64
|
+
case 'ArrowRight': {
|
|
65
|
+
setListboxHasVisualFocus(false);
|
|
66
|
+
setActiveIndex(() => null);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { createDropdownKeydownHandler };
|
|
@@ -8,7 +8,11 @@ function highlightText(text, keyword) {
|
|
|
8
8
|
return [];
|
|
9
9
|
if (!keyword)
|
|
10
10
|
return [{ text, highlight: false }];
|
|
11
|
-
|
|
11
|
+
// Ensure keyword is a string
|
|
12
|
+
const keywordString = String(keyword);
|
|
13
|
+
if (!keywordString)
|
|
14
|
+
return [{ text, highlight: false }];
|
|
15
|
+
const safeKeyword = keywordString.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
12
16
|
const regex = new RegExp(`(${safeKeyword})`, 'gi');
|
|
13
17
|
const parts = [];
|
|
14
18
|
let lastIndex = 0;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a shortcut key string into a formatted display string.
|
|
3
|
+
* @param shortcut - Shortcut key string (e.g., 'cmd+n', 'ctrl+n', 'k')
|
|
4
|
+
* @param isMac - Whether to format as Mac shortcut
|
|
5
|
+
* @returns Formatted display string
|
|
6
|
+
*/
|
|
7
|
+
export declare const formatShortcut: (shortcut: string | number, isMac: boolean) => string;
|
|
8
|
+
/**
|
|
9
|
+
* Converts an array of shortcut keys into a display string.
|
|
10
|
+
* Format: {mac_shortcut} / {windows_shortcut} / {other_keys}
|
|
11
|
+
*
|
|
12
|
+
* @param shortcutKeys - Array of shortcut keys
|
|
13
|
+
* @returns Formatted display string
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* shortcutTextHandler(['ctrl+n', 'cmd+n']) // '⌘N / Ctrl+N'
|
|
17
|
+
* shortcutTextHandler(['delete', 'backspace']) // 'Delete / Backspace'
|
|
18
|
+
* shortcutTextHandler(['k']) // 'K'
|
|
19
|
+
* shortcutTextHandler(['ctrl+r', 'cmd+r', 'f5']) // '⌘R / Ctrl+R / F5'
|
|
20
|
+
* shortcutTextHandler(['cmd+shift+n', 'ctrl+shift+n']) // '⌘⇧N / Ctrl+Shift+N'
|
|
21
|
+
* shortcutTextHandler(['cmd+option+n', 'ctrl+alt+n']) // '⌘⌥N / Ctrl+Alt+N'
|
|
22
|
+
*/
|
|
23
|
+
export declare const shortcutTextHandler: (shortcutKeys: Array<string | number>) => string;
|
|
24
|
+
export default shortcutTextHandler;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a shortcut key string into modifiers and main key.
|
|
3
|
+
* @param shortcut - Shortcut key string (e.g., 'cmd+shift+n', 'ctrl+alt+delete')
|
|
4
|
+
* @returns Object with modifiers and main key
|
|
5
|
+
*/
|
|
6
|
+
const parseShortcut = (shortcut) => {
|
|
7
|
+
const str = String(shortcut).toLowerCase();
|
|
8
|
+
const tokens = str
|
|
9
|
+
.split('+')
|
|
10
|
+
.map((token) => token.trim())
|
|
11
|
+
.filter(Boolean);
|
|
12
|
+
const modifiers = [];
|
|
13
|
+
let mainKey = null;
|
|
14
|
+
tokens.forEach((token) => {
|
|
15
|
+
switch (token) {
|
|
16
|
+
case 'cmd':
|
|
17
|
+
case 'meta':
|
|
18
|
+
case 'command':
|
|
19
|
+
modifiers.push('cmd');
|
|
20
|
+
break;
|
|
21
|
+
case 'ctrl':
|
|
22
|
+
case 'control':
|
|
23
|
+
modifiers.push('ctrl');
|
|
24
|
+
break;
|
|
25
|
+
case 'alt':
|
|
26
|
+
case 'option':
|
|
27
|
+
modifiers.push(token === 'option' ? 'option' : 'alt');
|
|
28
|
+
break;
|
|
29
|
+
case 'shift':
|
|
30
|
+
modifiers.push('shift');
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
if (!mainKey) {
|
|
34
|
+
mainKey = token;
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
return { modifiers, mainKey: mainKey || str };
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Formats a shortcut for Mac display.
|
|
43
|
+
* @param modifiers - Array of modifier keys
|
|
44
|
+
* @param mainKey - Main key
|
|
45
|
+
* @returns Formatted Mac shortcut string
|
|
46
|
+
*/
|
|
47
|
+
const formatMacShortcut = (modifiers, mainKey) => {
|
|
48
|
+
const symbols = [];
|
|
49
|
+
modifiers.forEach((mod) => {
|
|
50
|
+
switch (mod) {
|
|
51
|
+
case 'cmd':
|
|
52
|
+
symbols.push('⌘');
|
|
53
|
+
break;
|
|
54
|
+
case 'option':
|
|
55
|
+
symbols.push('⌥');
|
|
56
|
+
break;
|
|
57
|
+
case 'shift':
|
|
58
|
+
symbols.push('⇧');
|
|
59
|
+
break;
|
|
60
|
+
case 'ctrl':
|
|
61
|
+
symbols.push('⌃');
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
const formattedKey = mainKey.toUpperCase();
|
|
66
|
+
if (symbols.length > 0) {
|
|
67
|
+
return `${symbols.join('')}${formattedKey}`;
|
|
68
|
+
}
|
|
69
|
+
return formattedKey;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Formats a shortcut for Windows display.
|
|
73
|
+
* @param modifiers - Array of modifier keys
|
|
74
|
+
* @param mainKey - Main key
|
|
75
|
+
* @returns Formatted Windows shortcut string
|
|
76
|
+
*/
|
|
77
|
+
const formatWindowsShortcut = (modifiers, mainKey) => {
|
|
78
|
+
const parts = [];
|
|
79
|
+
modifiers.forEach((mod) => {
|
|
80
|
+
switch (mod) {
|
|
81
|
+
case 'ctrl':
|
|
82
|
+
parts.push('Ctrl');
|
|
83
|
+
break;
|
|
84
|
+
case 'alt':
|
|
85
|
+
parts.push('Alt');
|
|
86
|
+
break;
|
|
87
|
+
case 'shift':
|
|
88
|
+
parts.push('Shift');
|
|
89
|
+
break;
|
|
90
|
+
case 'cmd':
|
|
91
|
+
// Windows doesn't have cmd, but if present, treat as Ctrl
|
|
92
|
+
parts.push('Ctrl');
|
|
93
|
+
break;
|
|
94
|
+
case 'option':
|
|
95
|
+
// Option on Mac is Alt on Windows
|
|
96
|
+
parts.push('Alt');
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
const formattedKey = mainKey.charAt(0).toUpperCase() + mainKey.slice(1).toLowerCase();
|
|
101
|
+
if (parts.length > 0) {
|
|
102
|
+
return `${parts.join('+')}+${formattedKey}`;
|
|
103
|
+
}
|
|
104
|
+
return formattedKey;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Converts a shortcut key string into a formatted display string.
|
|
108
|
+
* @param shortcut - Shortcut key string (e.g., 'cmd+n', 'ctrl+n', 'k')
|
|
109
|
+
* @param isMac - Whether to format as Mac shortcut
|
|
110
|
+
* @returns Formatted display string
|
|
111
|
+
*/
|
|
112
|
+
const formatShortcut = (shortcut, isMac) => {
|
|
113
|
+
const { modifiers, mainKey } = parseShortcut(shortcut);
|
|
114
|
+
if (isMac) {
|
|
115
|
+
return formatMacShortcut(modifiers, mainKey);
|
|
116
|
+
}
|
|
117
|
+
return formatWindowsShortcut(modifiers, mainKey);
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Converts an array of shortcut keys into a display string.
|
|
121
|
+
* Format: {mac_shortcut} / {windows_shortcut} / {other_keys}
|
|
122
|
+
*
|
|
123
|
+
* @param shortcutKeys - Array of shortcut keys
|
|
124
|
+
* @returns Formatted display string
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* shortcutTextHandler(['ctrl+n', 'cmd+n']) // '⌘N / Ctrl+N'
|
|
128
|
+
* shortcutTextHandler(['delete', 'backspace']) // 'Delete / Backspace'
|
|
129
|
+
* shortcutTextHandler(['k']) // 'K'
|
|
130
|
+
* shortcutTextHandler(['ctrl+r', 'cmd+r', 'f5']) // '⌘R / Ctrl+R / F5'
|
|
131
|
+
* shortcutTextHandler(['cmd+shift+n', 'ctrl+shift+n']) // '⌘⇧N / Ctrl+Shift+N'
|
|
132
|
+
* shortcutTextHandler(['cmd+option+n', 'ctrl+alt+n']) // '⌘⌥N / Ctrl+Alt+N'
|
|
133
|
+
*/
|
|
134
|
+
const shortcutTextHandler = (shortcutKeys) => {
|
|
135
|
+
if (!shortcutKeys || shortcutKeys.length === 0) {
|
|
136
|
+
return '';
|
|
137
|
+
}
|
|
138
|
+
const mac = [];
|
|
139
|
+
const windows = [];
|
|
140
|
+
const others = [];
|
|
141
|
+
shortcutKeys.forEach((shortcut) => {
|
|
142
|
+
const { modifiers } = parseShortcut(shortcut);
|
|
143
|
+
const hasMacModifier = modifiers.includes('cmd') || modifiers.includes('option');
|
|
144
|
+
const hasWindowsModifier = modifiers.includes('ctrl') || modifiers.includes('alt');
|
|
145
|
+
if (hasMacModifier) {
|
|
146
|
+
mac.push(formatShortcut(shortcut, true));
|
|
147
|
+
}
|
|
148
|
+
else if (hasWindowsModifier) {
|
|
149
|
+
windows.push(formatShortcut(shortcut, false));
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// Single key or key with only shift
|
|
153
|
+
if (modifiers.includes('shift')) {
|
|
154
|
+
// Shift can be used on both platforms
|
|
155
|
+
mac.push(formatShortcut(shortcut, true));
|
|
156
|
+
windows.push(formatShortcut(shortcut, false));
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
others.push(formatShortcut(shortcut, false));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
// Remove duplicates and combine
|
|
164
|
+
const uniqueMac = Array.from(new Set(mac));
|
|
165
|
+
const uniqueWindows = Array.from(new Set(windows));
|
|
166
|
+
const uniqueOthers = Array.from(new Set(others));
|
|
167
|
+
const parts = [...uniqueMac, ...uniqueWindows, ...uniqueOthers];
|
|
168
|
+
return parts.join(' / ');
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export { shortcutTextHandler as default, formatShortcut, shortcutTextHandler };
|
package/Empty/Empty.js
CHANGED
|
@@ -8,6 +8,7 @@ import { EmptyMainInitialDataIcon } from './icons/EmptyMainInitialDataIcon.js';
|
|
|
8
8
|
import { EmptyMainResultIcon } from './icons/EmptyMainResultIcon.js';
|
|
9
9
|
import { EmptyMainSystemIcon } from './icons/EmptyMainSystemIcon.js';
|
|
10
10
|
import { flattenChildren } from '../utils/flatten-children.js';
|
|
11
|
+
import { EmptyMainNotificationIcon } from './icons/EmptyMainNotificationIcon.js';
|
|
11
12
|
import Icon from '../Icon/Icon.js';
|
|
12
13
|
import cx from 'clsx';
|
|
13
14
|
|
|
@@ -21,7 +22,7 @@ const iconMap = {
|
|
|
21
22
|
const mainIconMap = {
|
|
22
23
|
custom: null,
|
|
23
24
|
'initial-data': jsx(EmptyMainInitialDataIcon, { className: emptyClasses.icon }),
|
|
24
|
-
notification:
|
|
25
|
+
notification: jsx(EmptyMainNotificationIcon, { className: emptyClasses.icon }),
|
|
25
26
|
result: jsx(EmptyMainResultIcon, { className: emptyClasses.icon }),
|
|
26
27
|
system: jsx(EmptyMainSystemIcon, { className: emptyClasses.icon }),
|
|
27
28
|
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export interface EmptyMainNotificationIconProps extends React.SVGProps<SVGSVGElement> {
|
|
2
|
+
size?: number;
|
|
3
|
+
}
|
|
4
|
+
export declare const EmptyMainNotificationIcon: import("react").ForwardRefExoticComponent<Omit<EmptyMainNotificationIconProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
|
|
4
|
+
const EmptyMainNotificationIcon = forwardRef(function EmptyMainNotificationIcon(props, ref) {
|
|
5
|
+
const { className, size = 64, ...rest } = props;
|
|
6
|
+
return (jsxs("svg", { ...rest, className: className, fill: "none", height: size, ref: ref, viewBox: "0 0 44 47", width: size, xmlns: "http://www.w3.org/2000/svg", children: [jsxs("defs", { children: [jsxs("linearGradient", { gradientUnits: "userSpaceOnUse", id: "paint0_linear_8482_10235", x1: "22", x2: "20.7012", y1: "33", y2: "46.8785", children: [jsx("stop", { stopColor: "#9DA4AE" }), jsx("stop", { offset: "1", stopColor: "#E5E7EB" })] }), jsxs("linearGradient", { gradientUnits: "userSpaceOnUse", id: "paint1_linear_8482_10235", x1: "44", x2: "-3.06232", y1: "-1.43647e-06", y2: "35.9963", children: [jsx("stop", { stopColor: "#E5E7EB" }), jsx("stop", { offset: "1", stopColor: "#9DA4AE" })] })] }), jsx("circle", { cx: "22", cy: "40", fill: "url(#paint0_linear_8482_10235)", r: "7" }), jsx("path", { d: "M6.69446 15.305C6.69446 6.85228 13.5467 0 21.9995 0C30.4522 0 37.3045 6.85228 37.3045 15.305V26.5731C37.3045 26.6145 37.3141 26.6552 37.3326 26.6922L43.2746 38.5521C43.6077 39.217 43.1242 40 42.3805 40H1.61938C0.875674 40 0.392197 39.2171 0.725289 38.5521L6.66632 26.6922C6.68483 26.6552 6.69446 26.6145 6.69446 26.5731V15.305Z", fill: "url(#paint1_linear_8482_10235)" })] }));
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export { EmptyMainNotificationIcon };
|
package/Empty/typings.d.ts
CHANGED
|
@@ -13,14 +13,14 @@ export interface PresetPictogramEmptyProps {
|
|
|
13
13
|
* The type of empty state, which determines the icon and color theme.
|
|
14
14
|
* @default 'initial-data'
|
|
15
15
|
*/
|
|
16
|
-
type?: 'initial-data' | 'result' | 'system';
|
|
16
|
+
type?: 'initial-data' | 'result' | 'system' | 'notification';
|
|
17
17
|
/**
|
|
18
18
|
* Custom pictogram element.
|
|
19
19
|
*/
|
|
20
20
|
pictogram?: ReactNode;
|
|
21
21
|
}
|
|
22
22
|
export interface CustomPictogramEmptyProps {
|
|
23
|
-
type?: '
|
|
23
|
+
type?: 'custom';
|
|
24
24
|
pictogram?: ReactNode;
|
|
25
25
|
}
|
|
26
26
|
export interface MainOrSubEmptyProps {
|