@dloizides/ui-nav 1.13.0 → 1.15.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 CHANGED
@@ -1,5 +1,50 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.14.0
4
+
5
+ - **Feature (an expandable nav group now ANIMATES its expand/collapse instead of snapping).**
6
+ `NavExpandableItem` used to conditionally render its children (`{expanded ? … : null}`),
7
+ so a sidebar/drawer group's leaves appeared and vanished INSTANTLY on toggle — a hard,
8
+ jarring cut with no transition. The group's children are now wrapped in the
9
+ `@dloizides/ui-motion` `<Collapse open={expanded}>`, which measures the children's natural
10
+ height and animates a real `Animated.Value` height on WEB and native alike (the height code
11
+ path RN's native-only `LayoutAnimation` never gave the web build), collapsing to instant
12
+ under `prefers-reduced-motion`.
13
+ - **Collapsed leaves stay non-interactive.** Per the `Collapse` contract the children remain
14
+ MOUNTED at all times (their state and a11y focus order are preserved); when collapsed they
15
+ are clipped to zero height under `overflow: hidden`, so a collapsed group's leaves are
16
+ neither visible nor tappable in a real browser even though they are in the tree. This is a
17
+ deliberate change from the prior "absent from the DOM when collapsed" behaviour.
18
+ - **`aria-expanded` and the mobile-drawer contract are intact.** The group header still emits
19
+ `aria-expanded` (the `ariaExpandedProps` spread is unchanged), so `MobileDrawer` still tells
20
+ a group TOGGLE apart from a navigating LEAF and does not dismiss the drawer when a group is
21
+ expanded on mobile. The active-leaf accent bar, docs-style section-header styling, chevron
22
+ slot, testIDs, and all a11y roles/labels/hints are unchanged.
23
+ - **No public API change.** `NavExpandableItemProps` / `NavItem` are untouched — the animation
24
+ is derived from the `expanded` state the component already tracked. `@dloizides/ui-motion`
25
+ (`^1.0.1`) is added as a runtime dependency; all 7 portals gain the animated group on their
26
+ next bump for free. Consumers with no expandable groups are visually unaffected.
27
+
28
+ ## 1.13.1
29
+
30
+ - **Fix (mobile drawer: a sub-item / leaf tap dismissed the drawer WITHOUT navigating).**
31
+ On a phone-width viewport, tapping a leaf inside the open `MobileDrawer` closed the drawer
32
+ but the route never changed — verified live on finreg via Playwright (real Chromium, real
33
+ pointer events); every jsdom unit test stayed green because it wired `onClose` to an inert
34
+ `jest.fn()` that never unmounts anything.
35
+ - **Root cause.** `MobileDrawer` closes on a nav press via a NATIVE
36
+ `panel.addEventListener('click', …)`. react-native-web fires a leaf's `onPress` from its
37
+ `onClick`, dispatched through REACT's synthetic event system whose root listener sits on the
38
+ app-root container — an ANCESTOR of the panel. So on a real click the native panel listener
39
+ runs FIRST (during the DOM bubble), and closing synchronously there ran `setDrawerOpen(false)`,
40
+ unmounting the panel and tearing the leaf out of the tree BEFORE React could dispatch its
41
+ `onPress`. The navigation call never ran.
42
+ - **Fix.** The drawer's close is now DEFERRED to the next macrotask (`setTimeout(…, 0)`), so
43
+ React finishes dispatching the tapped leaf's `onPress` (the navigation) for the current click;
44
+ the panel then unmounts on the following tick, after the route has already changed. Scrim tap
45
+ and group-header toggle are unchanged.
46
+ - **No API change.** All 7 portals get the fix on their next bump.
47
+
3
48
  ## 1.11.0
4
49
 
5
50
  - **Feature (an expandable nav group now auto-opens when the current route is inside it).**
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  var reactNative = require('react-native');
4
4
  var uiFeedback = require('@dloizides/ui-feedback');
5
5
  var React2 = require('react');
6
+ var uiMotion = require('@dloizides/ui-motion');
6
7
  var jsxRuntime = require('react/jsx-runtime');
7
8
  var uiLayout = require('@dloizides/ui-layout');
8
9
  var authWeb = require('@dloizides/auth-web');
@@ -413,7 +414,7 @@ var NavExpandableItem = ({
413
414
  ]
414
415
  }
415
416
  ),
416
- expanded ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: expandableStyles.childrenContainer, children: item.children?.map((child) => /* @__PURE__ */ jsxRuntime.jsx(
417
+ /* @__PURE__ */ jsxRuntime.jsx(uiMotion.Collapse, { open: expanded, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: expandableStyles.childrenContainer, children: item.children?.map((child) => /* @__PURE__ */ jsxRuntime.jsx(
417
418
  NavExpandableItem,
418
419
  {
419
420
  collapseHint,
@@ -426,7 +427,7 @@ var NavExpandableItem = ({
426
427
  onNavigate
427
428
  },
428
429
  child.key
429
- )) }) : null
430
+ )) }) })
430
431
  ] });
431
432
  };
432
433
  function isBareText(node) {
@@ -1054,6 +1055,10 @@ var SCRIM_Z_INDEX = 1;
1054
1055
  var PANEL_Z_INDEX = 2;
1055
1056
  var NAV_ACTIVATABLE_SELECTOR = 'a, [role="button"], [role="link"]';
1056
1057
  var NAV_TOGGLE_SELECTOR = "[aria-expanded]";
1058
+ function deferClose(close) {
1059
+ if (typeof setTimeout === "function") setTimeout(close, 0);
1060
+ else close();
1061
+ }
1057
1062
  var DEFAULT_DRAWER_LABELS = {
1058
1063
  openLabel: "Menu",
1059
1064
  openHint: "Open the navigation menu",
@@ -1119,7 +1124,7 @@ var MobileDrawer = ({
1119
1124
  if (target === null) return;
1120
1125
  const activatable = target.closest(NAV_ACTIVATABLE_SELECTOR);
1121
1126
  const isToggle = activatable !== null && activatable.closest(NAV_TOGGLE_SELECTOR) !== null;
1122
- if (activatable !== null && !isToggle) onClose();
1127
+ if (activatable !== null && !isToggle) deferClose(onClose);
1123
1128
  };
1124
1129
  node.addEventListener("click", handleClick);
1125
1130
  return () => node.removeEventListener("click", handleClick);