@primer/react 38.30.0-rc.dc0369509 → 38.30.1-rc.2d1806208
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/CHANGELOG.md +18 -0
- package/dist/ActionBar/ActionBar.d.ts +24 -1
- package/dist/ActionBar/ActionBar.d.ts.map +1 -1
- package/dist/ActionBar/ActionBar.js +96 -4
- package/dist/ActionBar/index.d.ts +21 -1
- package/dist/ActionBar/index.d.ts.map +1 -1
- package/dist/ActionBar/index.js +2 -1
- package/dist/Heading/Heading.js +69 -19
- package/dist/Link/Link.js +81 -25
- package/dist/NavList/NavList-b50d982b.css +2 -0
- package/dist/NavList/NavList-b50d982b.css.map +1 -0
- package/dist/NavList/NavList.d.ts +13 -4
- package/dist/NavList/NavList.d.ts.map +1 -1
- package/dist/NavList/NavList.js +238 -70
- package/dist/NavList/NavList.module.css.js +2 -2
- package/dist/Pagehead/Pagehead.js +45 -11
- package/dist/SelectPanel/SelectPanel.d.ts +2 -2
- package/dist/SelectPanel/SelectPanel.d.ts.map +1 -1
- package/dist/SelectPanel/SelectPanel.js +4 -1
- package/dist/SideNav.js +112 -41
- package/dist/UnderlineNav/UnderlineNav-47547980.css +2 -0
- package/dist/UnderlineNav/UnderlineNav-47547980.css.map +1 -0
- package/dist/UnderlineNav/UnderlineNav.d.ts +1 -2
- package/dist/UnderlineNav/UnderlineNav.d.ts.map +1 -1
- package/dist/UnderlineNav/UnderlineNav.js +91 -331
- package/dist/UnderlineNav/UnderlineNav.module.css.js +2 -2
- package/dist/UnderlineNav/UnderlineNavContext.d.ts +1 -11
- package/dist/UnderlineNav/UnderlineNavContext.d.ts.map +1 -1
- package/dist/UnderlineNav/UnderlineNavContext.js +1 -4
- package/dist/UnderlineNav/UnderlineNavItem-402cd41c.css +2 -0
- package/dist/UnderlineNav/UnderlineNavItem-402cd41c.css.map +1 -0
- package/dist/UnderlineNav/UnderlineNavItem.d.ts +1 -44
- package/dist/UnderlineNav/UnderlineNavItem.d.ts.map +1 -1
- package/dist/UnderlineNav/UnderlineNavItem.js +33 -38
- package/dist/UnderlineNav/UnderlineNavItem.module.css.js +1 -1
- package/dist/UnderlineNav/UnderlineNavItemsRegistry.d.ts +51 -0
- package/dist/UnderlineNav/UnderlineNavItemsRegistry.d.ts.map +1 -0
- package/dist/UnderlineNav/UnderlineNavItemsRegistry.js +8 -0
- package/dist/UnderlineNav/index.d.ts +1 -1
- package/dist/UnderlineNav/index.d.ts.map +1 -1
- package/dist/UnderlineNav/utils.d.ts +2 -0
- package/dist/UnderlineNav/utils.d.ts.map +1 -1
- package/dist/UnderlineNav/utils.js +2 -1
- package/dist/experimental/UnderlinePanels/UnderlinePanels-162f9aed.css +2 -0
- package/dist/experimental/UnderlinePanels/UnderlinePanels-162f9aed.css.map +1 -0
- package/dist/experimental/UnderlinePanels/UnderlinePanels.d.ts.map +1 -1
- package/dist/experimental/UnderlinePanels/UnderlinePanels.js +8 -11
- package/dist/experimental/UnderlinePanels/UnderlinePanels.module.css.js +1 -1
- package/dist/internal/components/UnderlineTabbedInterface-1745a3d6.css +2 -0
- package/dist/internal/components/UnderlineTabbedInterface-1745a3d6.css.map +1 -0
- package/dist/internal/components/UnderlineTabbedInterface.d.ts +0 -1
- package/dist/internal/components/UnderlineTabbedInterface.d.ts.map +1 -1
- package/dist/internal/components/UnderlineTabbedInterface.js +66 -60
- package/dist/internal/components/UnderlineTabbedInterface.module.css.js +1 -1
- package/generated/components.json +72 -5
- package/package.json +1 -1
- package/dist/NavList/NavList-5dc067e3.css +0 -2
- package/dist/NavList/NavList-5dc067e3.css.map +0 -1
- package/dist/UnderlineNav/UnderlineNav-4344d9b0.css +0 -2
- package/dist/UnderlineNav/UnderlineNav-4344d9b0.css.map +0 -1
- package/dist/UnderlineNav/UnderlineNavItem-b65e8fd3.css +0 -2
- package/dist/UnderlineNav/UnderlineNavItem-b65e8fd3.css.map +0 -1
- package/dist/UnderlineNav/styles.d.ts +0 -16
- package/dist/UnderlineNav/styles.d.ts.map +0 -1
- package/dist/UnderlineNav/styles.js +0 -19
- package/dist/UnderlineNav/types.d.ts +0 -10
- package/dist/UnderlineNav/types.d.ts.map +0 -1
- package/dist/experimental/UnderlinePanels/UnderlinePanels-e4b325b9.css +0 -2
- package/dist/experimental/UnderlinePanels/UnderlinePanels-e4b325b9.css.map +0 -1
- package/dist/internal/components/UnderlineTabbedInterface-4197ee28.css +0 -2
- package/dist/internal/components/UnderlineTabbedInterface-4197ee28.css.map +0 -1
|
@@ -1,117 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { useDevOnlyEffect } from '../internal/hooks/useDevOnlyEffect.js';
|
|
3
|
-
import { UnderlineNavContext } from './UnderlineNavContext.js';
|
|
4
|
-
import { useResizeObserver } from '../hooks/useResizeObserver.js';
|
|
1
|
+
import { forwardRef, useRef, useState, useMemo } from 'react';
|
|
5
2
|
import VisuallyHidden from '../_VisuallyHidden.js';
|
|
6
|
-
import { dividerStyles, baseMenuMinWidth, menuItemStyles } from './styles.js';
|
|
7
|
-
import { UnderlineWrapper, UnderlineItemList, LoadingCounter, GAP } from '../internal/components/UnderlineTabbedInterface.js';
|
|
8
|
-
import { TriangleDownIcon } from '@primer/octicons-react';
|
|
9
|
-
import { useOnEscapePress } from '../hooks/useOnEscapePress.js';
|
|
10
|
-
import { useOnOutsideClick } from '../hooks/useOnOutsideClick.js';
|
|
11
|
-
import { useId } from '../hooks/useId.js';
|
|
12
3
|
import { ActionList } from '../ActionList/index.js';
|
|
4
|
+
import { UnderlineWrapper, UnderlineItemList, LoadingCounter } from '../internal/components/UnderlineTabbedInterface.js';
|
|
13
5
|
import { invariant } from '../utils/invariant.js';
|
|
14
6
|
import classes from './UnderlineNav.module.css.js';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
7
|
+
import { UnderlineNavContext } from './UnderlineNavContext.js';
|
|
8
|
+
import { UnderlineNavItemsRegistry } from './UnderlineNavItemsRegistry.js';
|
|
9
|
+
import { clsx } from 'clsx';
|
|
10
|
+
import { useDevOnlyEffect } from '../internal/hooks/useDevOnlyEffect.js';
|
|
11
|
+
import { isCurrent, getValidChildren } from './utils.js';
|
|
12
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
13
|
+
import { SkeletonText } from '../SkeletonText/SkeletonText.js';
|
|
19
14
|
import CounterLabel from '../CounterLabel/CounterLabel.js';
|
|
15
|
+
import { ActionMenu } from '../ActionMenu/ActionMenu.js';
|
|
20
16
|
|
|
21
|
-
// When page is loaded, we don't have ref for the more button as it is not on the DOM yet.
|
|
22
|
-
// However, we need to calculate number of possible items when the more button present as well. So using the width of the more button as a constant.
|
|
23
|
-
const MORE_BTN_WIDTH = 86;
|
|
24
|
-
// The height is needed to make sure we don't have a layout shift when the more button is the only item in the nav.
|
|
25
|
-
const MORE_BTN_HEIGHT = 45;
|
|
26
|
-
const overflowEffect = (navWidth, moreMenuWidth, childArray, childWidthArray, noIconChildWidthArray, updateListAndMenu) => {
|
|
27
|
-
let iconsVisible = true;
|
|
28
|
-
if (childWidthArray.length === 0) {
|
|
29
|
-
updateListAndMenu({
|
|
30
|
-
items: childArray,
|
|
31
|
-
menuItems: []
|
|
32
|
-
}, iconsVisible, false);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
const numberOfItemsPossible = calculatePossibleItems(childWidthArray, navWidth);
|
|
36
|
-
const numberOfItemsWithoutIconPossible = calculatePossibleItems(noIconChildWidthArray, navWidth);
|
|
37
|
-
// We need to take more menu width into account when calculating the number of items possible
|
|
38
|
-
const numberOfItemsPossibleWithMoreMenu = calculatePossibleItems(noIconChildWidthArray, navWidth, moreMenuWidth || MORE_BTN_WIDTH);
|
|
39
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
|
-
const items = [];
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
-
const menuItems = [];
|
|
43
|
-
|
|
44
|
-
// First, we check if we can fit all the items with their icons
|
|
45
|
-
if (childArray.length <= numberOfItemsPossible) {
|
|
46
|
-
items.push(...childArray);
|
|
47
|
-
} else if (childArray.length <= numberOfItemsWithoutIconPossible) {
|
|
48
|
-
// if we can't fit all the items with their icons, we check if we can fit all the items without their icons
|
|
49
|
-
iconsVisible = false;
|
|
50
|
-
items.push(...childArray);
|
|
51
|
-
} else {
|
|
52
|
-
// if we can't fit all the items without their icons, we keep the icons hidden and show the ones that doesn't fit into the list in the overflow menu
|
|
53
|
-
iconsVisible = false;
|
|
54
|
-
|
|
55
|
-
/* Below is an accessibility requirement. Never show only one item in the overflow menu.
|
|
56
|
-
* If there is only one item left to display in the overflow menu according to the calculation,
|
|
57
|
-
* we need to pull another item from the list into the overflow menu.
|
|
58
|
-
*/
|
|
59
|
-
const numberOfItemsInMenu = childArray.length - numberOfItemsPossibleWithMoreMenu;
|
|
60
|
-
const numberOfListItems = numberOfItemsInMenu === 1 ? numberOfItemsPossibleWithMoreMenu - 1 : numberOfItemsPossibleWithMoreMenu;
|
|
61
|
-
for (const [index, child] of childArray.entries()) {
|
|
62
|
-
if (index < numberOfListItems) {
|
|
63
|
-
items.push(child);
|
|
64
|
-
} else {
|
|
65
|
-
const ariaCurrent = child.props['aria-current'];
|
|
66
|
-
const isCurrent = Boolean(ariaCurrent) && ariaCurrent !== 'false';
|
|
67
|
-
// We need to make sure to keep the selected item always visible.
|
|
68
|
-
// To do that, we swap the selected item with the last item in the list to make it visible. (When there is at least 1 item in the list to swap.)
|
|
69
|
-
if (isCurrent && numberOfListItems > 0) {
|
|
70
|
-
// If selected item couldn't make in to the list, we swap it with the last item in the list.
|
|
71
|
-
const indexToReplaceAt = numberOfListItems - 1; // because we are replacing the last item in the list
|
|
72
|
-
// splice method modifies the array by removing 1 item here at the given index and replace it with the "child" element then returns the removed item.
|
|
73
|
-
const propsectiveAction = items.splice(indexToReplaceAt, 1, child)[0];
|
|
74
|
-
menuItems.push(propsectiveAction);
|
|
75
|
-
} else {
|
|
76
|
-
menuItems.push(child);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
updateListAndMenu({
|
|
82
|
-
items,
|
|
83
|
-
menuItems
|
|
84
|
-
}, iconsVisible, true);
|
|
85
|
-
};
|
|
86
|
-
const calculatePossibleItems = (childWidthArray, navWidth, moreMenuWidth = 0) => {
|
|
87
|
-
const widthToFit = navWidth - moreMenuWidth;
|
|
88
|
-
let breakpoint = childWidthArray.length; // assume all items will fit
|
|
89
|
-
let sumsOfChildWidth = 0;
|
|
90
|
-
for (const [index, childWidth] of childWidthArray.entries()) {
|
|
91
|
-
sumsOfChildWidth = sumsOfChildWidth + childWidth.width + GAP;
|
|
92
|
-
if (sumsOfChildWidth > widthToFit) {
|
|
93
|
-
breakpoint = index;
|
|
94
|
-
break;
|
|
95
|
-
} else {
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return breakpoint;
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
// Inline styles converted from baseMenuStyles for use as CSSProperties
|
|
103
|
-
const baseMenuInlineStyles = {
|
|
104
|
-
position: 'absolute',
|
|
105
|
-
zIndex: 1,
|
|
106
|
-
top: '90%',
|
|
107
|
-
boxShadow: '0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)',
|
|
108
|
-
borderRadius: 12,
|
|
109
|
-
background: 'var(--overlay-bgColor)',
|
|
110
|
-
listStyle: 'none',
|
|
111
|
-
minWidth: `${baseMenuMinWidth}px`,
|
|
112
|
-
maxWidth: '640px',
|
|
113
|
-
right: 0
|
|
114
|
-
};
|
|
115
17
|
const UnderlineNav = /*#__PURE__*/forwardRef(({
|
|
116
18
|
as = 'nav',
|
|
117
19
|
'aria-label': ariaLabel,
|
|
@@ -120,259 +22,117 @@ const UnderlineNav = /*#__PURE__*/forwardRef(({
|
|
|
120
22
|
className,
|
|
121
23
|
children
|
|
122
24
|
}, forwardedRef) => {
|
|
123
|
-
var
|
|
25
|
+
var _registeredItems$entr;
|
|
124
26
|
const backupRef = useRef(null);
|
|
125
27
|
const navRef = forwardedRef !== null && forwardedRef !== void 0 ? forwardedRef : backupRef;
|
|
126
28
|
const listRef = useRef(null);
|
|
127
|
-
const moreMenuRef = useRef(null);
|
|
128
|
-
const moreMenuBtnRef = useRef(null);
|
|
129
|
-
const containerRef = React.useRef(null);
|
|
130
|
-
const disclosureWidgetId = useId();
|
|
131
|
-
const [isWidgetOpen, setIsWidgetOpen] = useState(false);
|
|
132
|
-
const [iconsVisible, setIconsVisible] = useState(true);
|
|
133
|
-
const [childWidthArray, setChildWidthArray] = useState([]);
|
|
134
|
-
const [noIconChildWidthArray, setNoIconChildWidthArray] = useState([]);
|
|
135
|
-
// Track whether the initial overflow calculation is complete to prevent CLS
|
|
136
|
-
const [isOverflowMeasured, setIsOverflowMeasured] = useState(false);
|
|
137
|
-
const validChildren = getValidChildren(children);
|
|
138
|
-
|
|
139
|
-
// Responsive props object manages which items are in the list and which items are in the menu.
|
|
140
|
-
const [responsiveProps, setResponsiveProps] = useState({
|
|
141
|
-
items: validChildren,
|
|
142
|
-
menuItems: []
|
|
143
|
-
});
|
|
144
29
|
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
30
|
+
/** Tracks whether any item has ever overflowed for the lifecycle of this component. Used to prevent flickering. */
|
|
31
|
+
const [hasEverOverflowed, setHasOverflowed] = useState(false);
|
|
32
|
+
const [registeredItems, setRegisteredItems] = UnderlineNavItemsRegistry.useRegistryState();
|
|
33
|
+
const overflowMenuItems = Array.from((_registeredItems$entr = registeredItems === null || registeredItems === void 0 ? void 0 : registeredItems.entries()) !== null && _registeredItems$entr !== void 0 ? _registeredItems$entr : []).filter(entry => entry[1] !== null);
|
|
34
|
+
const isOverflowing = overflowMenuItems.length > 0;
|
|
35
|
+
if (isOverflowing && !hasEverOverflowed) setHasOverflowed(true);
|
|
150
36
|
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
});
|
|
156
|
-
// This is the case where the viewport is too narrow to show any list item with the more menu. In this case, we only show the dropdown
|
|
157
|
-
const onlyMenuVisible = responsiveProps.items.length === 0;
|
|
37
|
+
// Find the current item if it has overflowed into the menu, so we can reflect
|
|
38
|
+
// its "current" state on the overflow menu anchor.
|
|
39
|
+
const overflowingCurrentItem = overflowMenuItems.some(([, itemProps]) => isCurrent(itemProps));
|
|
40
|
+
const validChildren = getValidChildren(children);
|
|
158
41
|
useDevOnlyEffect(() => {
|
|
159
42
|
// Address illegal state where there are multiple items that have `aria-current='page'` attribute
|
|
160
|
-
const activeElements = validChildren.filter(child =>
|
|
161
|
-
return child.props['aria-current'] !== undefined;
|
|
162
|
-
});
|
|
43
|
+
const activeElements = validChildren.filter(child => isCurrent(child.props));
|
|
163
44
|
!(activeElements.length <= 1) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Only one current element is allowed') : invariant(false) : void 0;
|
|
164
45
|
!ariaLabel ? process.env.NODE_ENV !== "production" ? invariant(false, 'Use the `aria-label` prop to provide an accessible label for assistive technology') : invariant(false) : void 0;
|
|
165
46
|
}, [validChildren, ariaLabel]);
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const swapMenuItemWithListItem = (prospectiveListItem, indexOfProspectiveListItem, event, callback) => {
|
|
171
|
-
var _navRef$current$getBo, _navRef$current, _listRef$current$getB, _listRef$current;
|
|
172
|
-
// get the selected menu item's width
|
|
173
|
-
const widthToFitIntoList = getItemsWidth(prospectiveListItem.props.children);
|
|
174
|
-
// Check if there is any empty space on the right side of the list
|
|
175
|
-
const availableSpace = ((_navRef$current$getBo = (_navRef$current = navRef.current) === null || _navRef$current === void 0 ? void 0 : _navRef$current.getBoundingClientRect().width) !== null && _navRef$current$getBo !== void 0 ? _navRef$current$getBo : 0) - ((_listRef$current$getB = (_listRef$current = listRef.current) === null || _listRef$current === void 0 ? void 0 : _listRef$current.getBoundingClientRect().width) !== null && _listRef$current$getB !== void 0 ? _listRef$current$getB : 0);
|
|
47
|
+
const contextValue = useMemo(() => ({
|
|
48
|
+
loadingCounters
|
|
49
|
+
}), [loadingCounters]);
|
|
50
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
176
51
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const index = getBreakpointForItemSwapping(widthToFitIntoList, availableSpace);
|
|
180
|
-
const indexToSliceAt = responsiveProps.items.length - 1 - index;
|
|
181
|
-
// Form the new list of items
|
|
182
|
-
const itemsLeftInList = [...responsiveProps.items].slice(0, indexToSliceAt);
|
|
183
|
-
const updatedItemList = [...itemsLeftInList, prospectiveListItem];
|
|
184
|
-
// Form the new menu items
|
|
185
|
-
const itemsToAddToMenu = [...responsiveProps.items].slice(indexToSliceAt);
|
|
186
|
-
const updatedMenuItems = [...menuItems];
|
|
187
|
-
// Add itemsToAddToMenu array's items to the menu at the index of the prospectiveListItem and remove 1 count of items (prospectiveListItem)
|
|
188
|
-
updatedMenuItems.splice(indexOfProspectiveListItem, 1, ...itemsToAddToMenu);
|
|
189
|
-
callback({
|
|
190
|
-
items: updatedItemList,
|
|
191
|
-
menuItems: updatedMenuItems
|
|
192
|
-
}, false, true);
|
|
193
|
-
};
|
|
194
|
-
// How many items do we need to pull in to the menu to make room for the selected menu item.
|
|
195
|
-
function getBreakpointForItemSwapping(widthToFitIntoList, availableSpace) {
|
|
196
|
-
let widthToSwap = 0;
|
|
197
|
-
let breakpoint = 0;
|
|
198
|
-
for (const [index, item] of [...responsiveProps.items].reverse().entries()) {
|
|
199
|
-
widthToSwap += getItemsWidth(item.props.children);
|
|
200
|
-
if (widthToFitIntoList < widthToSwap + availableSpace) {
|
|
201
|
-
breakpoint = index;
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return breakpoint;
|
|
206
|
-
}
|
|
207
|
-
const updateListAndMenu = useCallback((props, displayIcons, overflowMeasured) => {
|
|
208
|
-
setResponsiveProps(props);
|
|
209
|
-
setIconsVisible(displayIcons);
|
|
210
|
-
if (overflowMeasured) {
|
|
211
|
-
setIsOverflowMeasured(true);
|
|
212
|
-
}
|
|
213
|
-
}, []);
|
|
214
|
-
const setChildrenWidth = useCallback(size => {
|
|
215
|
-
setChildWidthArray(arr => {
|
|
216
|
-
const newArr = [...arr, size];
|
|
217
|
-
return newArr;
|
|
218
|
-
});
|
|
219
|
-
}, []);
|
|
220
|
-
const setNoIconChildrenWidth = useCallback(size => {
|
|
221
|
-
setNoIconChildWidthArray(arr => {
|
|
222
|
-
const newArr = [...arr, size];
|
|
223
|
-
return newArr;
|
|
224
|
-
});
|
|
225
|
-
}, []);
|
|
226
|
-
const closeOverlay = React.useCallback(() => {
|
|
227
|
-
setIsWidgetOpen(false);
|
|
228
|
-
}, [setIsWidgetOpen]);
|
|
229
|
-
const focusOnMoreMenuBtn = React.useCallback(() => {
|
|
230
|
-
var _moreMenuBtnRef$curre;
|
|
231
|
-
(_moreMenuBtnRef$curre = moreMenuBtnRef.current) === null || _moreMenuBtnRef$curre === void 0 ? void 0 : _moreMenuBtnRef$curre.focus();
|
|
232
|
-
}, []);
|
|
233
|
-
const onAnchorClick = useCallback(event => {
|
|
234
|
-
if (event.defaultPrevented || event.button !== 0) {
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
setIsWidgetOpen(isWidgetOpen => !isWidgetOpen);
|
|
238
|
-
}, []);
|
|
239
|
-
useOnEscapePress(event => {
|
|
240
|
-
if (isWidgetOpen) {
|
|
241
|
-
event.preventDefault();
|
|
242
|
-
closeOverlay();
|
|
243
|
-
focusOnMoreMenuBtn();
|
|
244
|
-
}
|
|
245
|
-
}, [isWidgetOpen]);
|
|
246
|
-
useOnOutsideClick({
|
|
247
|
-
onClickOutside: closeOverlay,
|
|
248
|
-
containerRef,
|
|
249
|
-
ignoreClickRefs: [moreMenuBtnRef]
|
|
250
|
-
});
|
|
251
|
-
useResizeObserver(resizeObserverEntries => {
|
|
252
|
-
var _moreMenuRef$current$, _moreMenuRef$current;
|
|
253
|
-
const navWidth = resizeObserverEntries[0].contentRect.width;
|
|
254
|
-
const moreMenuWidth = (_moreMenuRef$current$ = (_moreMenuRef$current = moreMenuRef.current) === null || _moreMenuRef$current === void 0 ? void 0 : _moreMenuRef$current.getBoundingClientRect().width) !== null && _moreMenuRef$current$ !== void 0 ? _moreMenuRef$current$ : 0;
|
|
255
|
-
navWidth !== 0 && overflowEffect(navWidth, moreMenuWidth, validChildren, childWidthArray, noIconChildWidthArray, updateListAndMenu);
|
|
256
|
-
}, navRef);
|
|
257
|
-
|
|
258
|
-
// Compute menuInlineStyles if needed
|
|
259
|
-
let menuInlineStyles = {
|
|
260
|
-
...baseMenuInlineStyles
|
|
261
|
-
};
|
|
262
|
-
if (containerRef.current && listRef.current) {
|
|
263
|
-
const {
|
|
264
|
-
left
|
|
265
|
-
} = getAnchoredPosition(containerRef.current, listRef.current, {
|
|
266
|
-
align: 'start',
|
|
267
|
-
side: 'outside-bottom'
|
|
268
|
-
});
|
|
269
|
-
menuInlineStyles = {
|
|
270
|
-
...baseMenuInlineStyles,
|
|
271
|
-
right: undefined,
|
|
272
|
-
left
|
|
273
|
-
};
|
|
274
|
-
}
|
|
52
|
+
// Edge case to avoid empty menu: close the menu if it's open but there's no longer an overflow (window resized or items removed)
|
|
53
|
+
if (menuOpen && !isOverflowing) setMenuOpen(false);
|
|
275
54
|
return /*#__PURE__*/jsxs(UnderlineNavContext.Provider, {
|
|
276
|
-
value:
|
|
277
|
-
setChildrenWidth,
|
|
278
|
-
setNoIconChildrenWidth,
|
|
279
|
-
loadingCounters,
|
|
280
|
-
iconsVisible
|
|
281
|
-
},
|
|
55
|
+
value: contextValue,
|
|
282
56
|
children: [ariaLabel && /*#__PURE__*/jsx(VisuallyHidden, {
|
|
283
57
|
as: "h2",
|
|
284
58
|
children: `${ariaLabel} navigation`
|
|
285
|
-
}), /*#__PURE__*/
|
|
59
|
+
}), /*#__PURE__*/jsxs(UnderlineWrapper, {
|
|
286
60
|
as: as,
|
|
287
61
|
"aria-label": ariaLabel,
|
|
288
|
-
className: className,
|
|
62
|
+
className: clsx(classes.UnderlineWrapper, className),
|
|
289
63
|
ref: navRef,
|
|
290
64
|
"data-variant": variant,
|
|
291
|
-
"data-overflow-
|
|
292
|
-
|
|
65
|
+
"data-overflow-mode": "wrap"
|
|
66
|
+
// Force icons to stay hidden, avoiding flickering as icons create/remove overflow
|
|
67
|
+
,
|
|
68
|
+
"data-hide-icons": hasEverOverflowed ? 'true' : undefined
|
|
69
|
+
// Ensure button is shown (after initial render) on browsers that don't support scroll-driven animations
|
|
70
|
+
,
|
|
71
|
+
"data-has-overflow": isOverflowing ? 'true' : undefined,
|
|
72
|
+
children: [/*#__PURE__*/jsx(UnderlineItemList, {
|
|
293
73
|
ref: listRef,
|
|
294
74
|
role: "list",
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
75
|
+
className: classes.ItemsList,
|
|
76
|
+
children: /*#__PURE__*/jsx(UnderlineNavItemsRegistry.Provider, {
|
|
77
|
+
setRegistry: setRegisteredItems,
|
|
78
|
+
children: children
|
|
79
|
+
})
|
|
80
|
+
}), /*#__PURE__*/jsxs("div", {
|
|
81
|
+
className: classes.MoreButtonContainer,
|
|
82
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
83
|
+
className: classes.MoreButtonDivider
|
|
84
|
+
}), /*#__PURE__*/jsxs(ActionMenu, {
|
|
85
|
+
open: menuOpen,
|
|
86
|
+
onOpenChange: setMenuOpen,
|
|
87
|
+
children: [/*#__PURE__*/jsx(ActionMenu.Button, {
|
|
306
88
|
className: classes.MoreButton,
|
|
307
|
-
"
|
|
308
|
-
"
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
children: /*#__PURE__*/
|
|
312
|
-
children:
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}), "Menu"]
|
|
317
|
-
}) : /*#__PURE__*/jsxs(Fragment, {
|
|
318
|
-
children: ["More", /*#__PURE__*/jsxs(VisuallyHidden, {
|
|
319
|
-
as: "span",
|
|
320
|
-
children: ["\xA0", `${ariaLabel} items`]
|
|
321
|
-
})]
|
|
322
|
-
})
|
|
89
|
+
variant: "invisible",
|
|
90
|
+
"data-component": "overflow-menu-button",
|
|
91
|
+
"data-current": overflowingCurrentItem ? 'true' : undefined,
|
|
92
|
+
"aria-label": overflowingCurrentItem ? `More items, including current item` : undefined,
|
|
93
|
+
children: /*#__PURE__*/jsxs("span", {
|
|
94
|
+
children: ["More", /*#__PURE__*/jsx(VisuallyHidden, {
|
|
95
|
+
as: "span",
|
|
96
|
+
children: " items"
|
|
97
|
+
})]
|
|
323
98
|
})
|
|
324
|
-
}), /*#__PURE__*/jsx(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
onClick: event => {
|
|
351
|
-
// When there are no items in the list, do not run the swap function as we want to keep everything in the menu.
|
|
352
|
-
!onlyMenuVisible && swapMenuItemWithListItem(menuItem, index, event, updateListAndMenu);
|
|
353
|
-
closeOverlay();
|
|
354
|
-
focusOnMoreMenuBtn();
|
|
355
|
-
// fire onSelect event that comes from the UnderlineNav.Item (if it is defined)
|
|
356
|
-
typeof onSelect === 'function' && onSelect(event);
|
|
357
|
-
},
|
|
358
|
-
...menuItemProps,
|
|
359
|
-
children: /*#__PURE__*/jsxs("span", {
|
|
360
|
-
className: classes.MenuItemContent,
|
|
361
|
-
children: [menuItemChildren, loadingCounters ? /*#__PURE__*/jsx(LoadingCounter, {}) : counter !== undefined && /*#__PURE__*/jsx("span", {
|
|
362
|
-
"data-component": "counter",
|
|
363
|
-
children: /*#__PURE__*/jsx(CounterLabel, {
|
|
364
|
-
children: counter
|
|
99
|
+
}), /*#__PURE__*/jsx(ActionMenu.Overlay, {
|
|
100
|
+
children: /*#__PURE__*/jsx(ActionList, {
|
|
101
|
+
children: registeredItems === undefined ? /*#__PURE__*/jsx(ActionList.Item, {
|
|
102
|
+
children: /*#__PURE__*/jsx(SkeletonText, {})
|
|
103
|
+
}) : overflowMenuItems.map(([key, allProps]) => {
|
|
104
|
+
const {
|
|
105
|
+
children: menuItemChildren,
|
|
106
|
+
counter,
|
|
107
|
+
onSelect,
|
|
108
|
+
...menuItemProps
|
|
109
|
+
} = allProps;
|
|
110
|
+
return /*#__PURE__*/jsxs(ActionList.LinkItem, {
|
|
111
|
+
onClick: event => onSelect === null || onSelect === void 0 ? void 0 : onSelect(event),
|
|
112
|
+
...menuItemProps,
|
|
113
|
+
className: classes.OverflowMenuItem,
|
|
114
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
115
|
+
className: classes.OverflowMenuItemLabel,
|
|
116
|
+
children: menuItemChildren
|
|
117
|
+
}), loadingCounters ? /*#__PURE__*/jsx(ActionList.TrailingVisual, {
|
|
118
|
+
children: /*#__PURE__*/jsx(LoadingCounter, {})
|
|
119
|
+
}) : counter !== undefined && /*#__PURE__*/jsx(ActionList.TrailingVisual, {
|
|
120
|
+
children: /*#__PURE__*/jsx("span", {
|
|
121
|
+
"data-component": "counter",
|
|
122
|
+
children: /*#__PURE__*/jsx(CounterLabel, {
|
|
123
|
+
children: counter
|
|
124
|
+
})
|
|
365
125
|
})
|
|
366
126
|
})]
|
|
367
|
-
})
|
|
368
|
-
}
|
|
127
|
+
}, key);
|
|
128
|
+
})
|
|
369
129
|
})
|
|
370
130
|
})]
|
|
371
131
|
})]
|
|
372
|
-
})
|
|
132
|
+
})]
|
|
373
133
|
})]
|
|
374
134
|
});
|
|
375
135
|
});
|
|
376
136
|
UnderlineNav.displayName = 'UnderlineNav';
|
|
377
137
|
|
|
378
|
-
export {
|
|
138
|
+
export { UnderlineNav };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import './UnderlineNav-
|
|
1
|
+
import './UnderlineNav-47547980.css';
|
|
2
2
|
|
|
3
|
-
var classes = {"
|
|
3
|
+
var classes = {"UnderlineWrapper":"prc-UnderlineNav-UnderlineWrapper-GWONT","detect-overflow":"prc-UnderlineNav-detect-overflow-6HuSH","ItemsList":"prc-UnderlineNav-ItemsList-oj8gN","MoreButtonContainer":"prc-UnderlineNav-MoreButtonContainer-Dnrq6","OverflowMenuItem":"prc-UnderlineNav-OverflowMenuItem-7SG7M","OverflowMenuItemLabel":"prc-UnderlineNav-OverflowMenuItemLabel-F80v6","MoreButtonDivider":"prc-UnderlineNav-MoreButtonDivider-dN0a-","MoreButton":"prc-UnderlineNav-MoreButton-Y8soj"};
|
|
4
4
|
|
|
5
5
|
export { classes as default };
|
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const UnderlineNavContext: React.Context<{
|
|
3
|
-
setChildrenWidth: React.Dispatch<{
|
|
4
|
-
text: string;
|
|
5
|
-
width: number;
|
|
6
|
-
}>;
|
|
7
|
-
setNoIconChildrenWidth: React.Dispatch<{
|
|
8
|
-
text: string;
|
|
9
|
-
width: number;
|
|
10
|
-
}>;
|
|
1
|
+
export declare const UnderlineNavContext: import("react").Context<{
|
|
11
2
|
loadingCounters: boolean;
|
|
12
|
-
iconsVisible: boolean;
|
|
13
3
|
}>;
|
|
14
4
|
//# sourceMappingURL=UnderlineNavContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UnderlineNavContext.d.ts","sourceRoot":"","sources":["../../src/UnderlineNav/UnderlineNavContext.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"UnderlineNavContext.d.ts","sourceRoot":"","sources":["../../src/UnderlineNav/UnderlineNavContext.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB;qBACb,OAAO;EAGxB,CAAA"}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { createContext } from 'react';
|
|
2
2
|
|
|
3
3
|
const UnderlineNavContext = /*#__PURE__*/createContext({
|
|
4
|
-
|
|
5
|
-
setNoIconChildrenWidth: () => null,
|
|
6
|
-
loadingCounters: false,
|
|
7
|
-
iconsVisible: true
|
|
4
|
+
loadingCounters: false
|
|
8
5
|
});
|
|
9
6
|
|
|
10
7
|
export { UnderlineNavContext };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/UnderlineNav/UnderlineNavItem.module.css.js"],"names":[],"mappings":"AAAA,yCAGE,kBAAmB,CAFnB,YAAa,CACb,qBAAsB,CAEtB,eAOF,CALE,sDAGE,iBACF","file":"UnderlineNavItem-402cd41c.css","sourcesContent":[".UnderlineNavItem {\n display: flex;\n flex-direction: column;\n align-items: center;\n overflow: hidden;\n\n &[aria-hidden] {\n /* Overflowing items will already be clipped out of view, but might as well\n also hide them for performance and to ensure they can't accidentally appear */\n visibility: hidden;\n }\n}\n"]}
|
|
@@ -1,47 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { IconProps } from '@primer/octicons-react';
|
|
3
1
|
import type { ForwardRefComponent as PolymorphicForwardRefComponent } from '../utils/polymorphic';
|
|
4
|
-
|
|
5
|
-
download?: string;
|
|
6
|
-
href?: string;
|
|
7
|
-
hrefLang?: string;
|
|
8
|
-
media?: string;
|
|
9
|
-
ping?: string;
|
|
10
|
-
rel?: string;
|
|
11
|
-
target?: string;
|
|
12
|
-
type?: string;
|
|
13
|
-
referrerPolicy?: React.AnchorHTMLAttributes<HTMLAnchorElement>['referrerPolicy'];
|
|
14
|
-
};
|
|
15
|
-
export type UnderlineNavItemProps = {
|
|
16
|
-
/**
|
|
17
|
-
* Primary content for an UnderlineNav
|
|
18
|
-
*/
|
|
19
|
-
children?: React.ReactNode;
|
|
20
|
-
/**
|
|
21
|
-
* Callback that will trigger both on click selection and keyboard selection.
|
|
22
|
-
*/
|
|
23
|
-
onSelect?: (event: React.MouseEvent<HTMLAnchorElement> | React.KeyboardEvent<HTMLAnchorElement>) => void;
|
|
24
|
-
/**
|
|
25
|
-
* Is `UnderlineNav.Item` current page?
|
|
26
|
-
*/
|
|
27
|
-
'aria-current'?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false' | boolean;
|
|
28
|
-
/**
|
|
29
|
-
* Icon before the text
|
|
30
|
-
* @deprecated Use the `leadingVisual` prop instead
|
|
31
|
-
*/
|
|
32
|
-
icon?: React.FunctionComponent<IconProps> | React.ReactElement<any>;
|
|
33
|
-
/**
|
|
34
|
-
* Render a visual before the text
|
|
35
|
-
*/
|
|
36
|
-
leadingVisual?: React.ReactElement;
|
|
37
|
-
/**
|
|
38
|
-
* Renders `UnderlineNav.Item` as given component i.e. react-router's Link
|
|
39
|
-
**/
|
|
40
|
-
as?: React.ElementType | 'a';
|
|
41
|
-
/**
|
|
42
|
-
* Counter
|
|
43
|
-
*/
|
|
44
|
-
counter?: number | string;
|
|
45
|
-
} & LinkProps;
|
|
2
|
+
import { type UnderlineNavItemProps } from './UnderlineNavItemsRegistry';
|
|
46
3
|
export declare const UnderlineNavItem: PolymorphicForwardRefComponent<"a", UnderlineNavItemProps>;
|
|
47
4
|
//# sourceMappingURL=UnderlineNavItem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UnderlineNavItem.d.ts","sourceRoot":"","sources":["../../src/UnderlineNav/UnderlineNavItem.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"UnderlineNavItem.d.ts","sourceRoot":"","sources":["../../src/UnderlineNav/UnderlineNavItem.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,mBAAmB,IAAI,8BAA8B,EAAC,MAAM,sBAAsB,CAAA;AAI/F,OAAO,EAAC,KAAK,qBAAqB,EAA4B,MAAM,6BAA6B,CAAA;AAEjG,eAAO,MAAM,gBAAgB,EA0EvB,8BAA8B,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAA"}
|