@dloizides/ui-nav 1.10.1 → 1.11.0
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 +45 -0
- package/dist/index.js +35 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +35 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.11.0
|
|
4
|
+
|
|
5
|
+
- **Feature (an expandable nav group now auto-opens when the current route is inside it).**
|
|
6
|
+
`NavExpandableItem` used to mount every group collapsed (`useState(false)`), so on a fresh
|
|
7
|
+
page load the group containing the active route was closed and its active leaf was hidden.
|
|
8
|
+
A persistent-rail console that groups its nav by module (e.g. finreg-web's Payments / CRM /
|
|
9
|
+
Accounting rail) needs the active module's group open on load, the others collapsed — with
|
|
10
|
+
no way for the caller to express that, since expansion state was internal and uncontrolled.
|
|
11
|
+
- The group now initializes its expansion from whether the current route is inside it:
|
|
12
|
+
`useState(() => hasActiveDescendant(item, pathname))`, where `hasActiveDescendant` is true
|
|
13
|
+
when the item's own route is active (`isRouteActive`) or any descendant's is (recursive, so
|
|
14
|
+
it holds at any nesting depth). The group of the active route mounts EXPANDED (active leaf
|
|
15
|
+
visible + highlighted); a group with no active descendant mounts COLLAPSED — exactly the
|
|
16
|
+
prior behaviour.
|
|
17
|
+
- **No API change.** `NavItem` is unchanged — the behaviour is derived from the `pathname`
|
|
18
|
+
the component already receives. Consumers with no expandable groups, or whose groups hold no
|
|
19
|
+
active route, are byte-for-byte unaffected; all 7 portals gain the auto-open on their next
|
|
20
|
+
bump for free.
|
|
21
|
+
- Guarded by `src/navExpandableItem.test.tsx` (RED-first): the two "mounts EXPANDED" assertions
|
|
22
|
+
FAIL against the pre-change `useState(false)` (the active group's child is absent from the DOM)
|
|
23
|
+
and pass after; the "mounts COLLAPSED" + "header always renders" assertions lock the
|
|
24
|
+
backward-compatible half.
|
|
25
|
+
|
|
26
|
+
## 1.10.2
|
|
27
|
+
|
|
28
|
+
- **Fix (the mobile nav DRAWER was not clickable — a tap on a nav item did not navigate, it
|
|
29
|
+
just closed the drawer / did nothing, in all seven portals below 768px).**
|
|
30
|
+
`MobileDrawer` rendered a full-bleed scrim `Pressable` (`StyleSheet.absoluteFillObject`) and a
|
|
31
|
+
panel `View` with `{ position: 'absolute', top: 0, bottom: 0, left: 0 }` — **no width and no
|
|
32
|
+
zIndex**. Reproduced structurally: the panel's computed `width` was empty and its `zIndex` was
|
|
33
|
+
`0`; the scrim's computed `left`/`right` were both `0px` at `zIndex` `0`. So the scrim FULLY
|
|
34
|
+
overlapped the panel at the SAME stacking level, and on react-native-web the equal-zIndex scrim
|
|
35
|
+
won the pointer (the estate's known "RN-web Pressable swallows a sibling/child press" trap):
|
|
36
|
+
the tap closed the drawer and the nav-item's `TouchableOpacity` `onPress` (→ the app's router)
|
|
37
|
+
never fired.
|
|
38
|
+
- Fixed once, in the kit: the panel now has an explicit drawer **width** (`280px`), a solid
|
|
39
|
+
surface background, and a `zIndex` **above** the scrim; the scrim is anchored BESIDE the panel
|
|
40
|
+
(`left: DRAWER_WIDTH`) so its tap-to-close hit area never overlaps the panel. Nav-item taps
|
|
41
|
+
reach the `Sidebar` leaves; taps beside the drawer still close it.
|
|
42
|
+
- Guarded by `src/mobileDrawer.test.tsx` (RED-first): three structural assertions read the
|
|
43
|
+
resolved geometry via `getComputedStyle` and FAIL against the pre-fix panel/scrim (no width,
|
|
44
|
+
equal zIndex, overlapping scrim); two behavioural assertions lock the contract (nav-item tap
|
|
45
|
+
navigates + closes; scrim tap only closes).
|
|
46
|
+
- **No API change.** Consumers need no edit — bump the dependency and the drawer works.
|
|
47
|
+
|
|
3
48
|
## 1.10.1
|
|
4
49
|
|
|
5
50
|
- **Fix (a plain-string slot logged `console.error` on EVERY render, in all seven portals).**
|
package/dist/index.js
CHANGED
|
@@ -289,6 +289,10 @@ function hoverTransitionStyle(reducedMotion) {
|
|
|
289
289
|
function ariaCurrentProps(isActive) {
|
|
290
290
|
return isActive ? { "aria-current": "page" } : {};
|
|
291
291
|
}
|
|
292
|
+
function hasActiveDescendant(item, pathname) {
|
|
293
|
+
if (isRouteActive(pathname, item.route)) return true;
|
|
294
|
+
return (item.children ?? []).some((child) => hasActiveDescendant(child, pathname));
|
|
295
|
+
}
|
|
292
296
|
var NavExpandableItem = ({
|
|
293
297
|
item,
|
|
294
298
|
pathname,
|
|
@@ -299,7 +303,7 @@ var NavExpandableItem = ({
|
|
|
299
303
|
renderChevron,
|
|
300
304
|
depth = 0
|
|
301
305
|
}) => {
|
|
302
|
-
const [expanded, setExpanded] = React2.useState(
|
|
306
|
+
const [expanded, setExpanded] = React2.useState(() => hasActiveDescendant(item, pathname));
|
|
303
307
|
const [focused, setFocused] = React2.useState(false);
|
|
304
308
|
const { theme } = uiFeedback.useUi();
|
|
305
309
|
const colors = theme.colors;
|
|
@@ -1004,6 +1008,9 @@ var MENU_MIN_TARGET = 44;
|
|
|
1004
1008
|
var MENU_GLYPH_FONT_SIZE = 20;
|
|
1005
1009
|
var MENU_TOGGLE_PADDING = 12;
|
|
1006
1010
|
var DRAWER_Z_INDEX = 50;
|
|
1011
|
+
var DRAWER_WIDTH = 280;
|
|
1012
|
+
var SCRIM_Z_INDEX = 1;
|
|
1013
|
+
var PANEL_Z_INDEX = 2;
|
|
1007
1014
|
var NAV_ACTIVATABLE_SELECTOR = 'a, [role="button"], [role="link"]';
|
|
1008
1015
|
var DEFAULT_DRAWER_LABELS = {
|
|
1009
1016
|
openLabel: "Menu",
|
|
@@ -1013,8 +1020,22 @@ var DEFAULT_DRAWER_LABELS = {
|
|
|
1013
1020
|
};
|
|
1014
1021
|
var styles2 = reactNative.StyleSheet.create({
|
|
1015
1022
|
overlay: { ...reactNative.StyleSheet.absoluteFillObject, zIndex: DRAWER_Z_INDEX },
|
|
1016
|
-
scrim
|
|
1017
|
-
|
|
1023
|
+
// The scrim's tap-to-close hit area is anchored to the RIGHT of the panel
|
|
1024
|
+
// (`left: DRAWER_WIDTH`), so it NEVER overlaps the panel: nav-item taps always
|
|
1025
|
+
// reach the Sidebar's TouchableOpacity, while taps beside the drawer still close.
|
|
1026
|
+
scrim: {
|
|
1027
|
+
position: "absolute",
|
|
1028
|
+
top: 0,
|
|
1029
|
+
bottom: 0,
|
|
1030
|
+
left: DRAWER_WIDTH,
|
|
1031
|
+
right: 0,
|
|
1032
|
+
backgroundColor: SCRIM_COLOR,
|
|
1033
|
+
zIndex: SCRIM_Z_INDEX
|
|
1034
|
+
},
|
|
1035
|
+
// The panel gets an explicit width (a real drawer) AND a zIndex above the scrim,
|
|
1036
|
+
// so on react-native-web it — and the nav leaves inside it — sit above the scrim
|
|
1037
|
+
// and receive presses instead of the scrim swallowing them.
|
|
1038
|
+
panel: { position: "absolute", top: 0, bottom: 0, left: 0, width: DRAWER_WIDTH, zIndex: PANEL_Z_INDEX },
|
|
1018
1039
|
menuToggle: {
|
|
1019
1040
|
minWidth: MENU_MIN_TARGET,
|
|
1020
1041
|
minHeight: MENU_MIN_TARGET,
|
|
@@ -1071,7 +1092,17 @@ var MobileDrawer = ({
|
|
|
1071
1092
|
onPress: onClose
|
|
1072
1093
|
}
|
|
1073
1094
|
),
|
|
1074
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1095
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1096
|
+
reactNative.View,
|
|
1097
|
+
{
|
|
1098
|
+
ref: panelRef,
|
|
1099
|
+
"aria-modal": true,
|
|
1100
|
+
role: "dialog",
|
|
1101
|
+
style: [styles2.panel, { backgroundColor: theme.colors.surface }],
|
|
1102
|
+
testID: drawerTestID,
|
|
1103
|
+
children: renderTextSlot(sidebar, { color: theme.colors.text })
|
|
1104
|
+
}
|
|
1105
|
+
)
|
|
1075
1106
|
] });
|
|
1076
1107
|
};
|
|
1077
1108
|
|