@dloizides/ui-nav 1.37.0 → 1.38.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,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.38.0
4
+
5
+ - NAV-BRAND-1 D-NAVB-3 "One brand options prop": `NavShell` takes one `brand={{ placement, railWidth, drawerHeader, drawerWidth }}` prop instead of the four 1.37.0 props; `Sidebar.width` removed (the shell sets the rail width through `containerStyle`). The top-bar brand cell carries the top bar background and bottom border, so the header line runs over the rail.
6
+
3
7
  ## 1.37.0
4
8
 
5
9
  - NAV-BRAND-1 "Wider sidebar, logo and name in the top bar": `NavShell` gains `brandPlacement`, `sidebarWidth`, `drawerHeader`, `drawerWidth` (defaults = today); `Sidebar.width`; `AppShell.mobileMenu` takes `header` / `width` / `sidebar`. Exports `SIDEBAR_WIDTH_PX`, `NAV_BRAND_DEFAULTS`.
package/README.md CHANGED
@@ -153,17 +153,17 @@ import { NavShell, type NavItem } from '@dloizides/ui-nav';
153
153
 
154
154
  ### Brand position, rail width and phone drawer (`NavShell`, NAV-BRAND-1)
155
155
 
156
- One prop per choice; every default keeps today's layout.
156
+ One `brand` prop holds every choice; every default (`NAV_BRAND_DEFAULTS`) keeps today's layout.
157
157
 
158
- | Prop | Values | Default |
158
+ | `brand` field | Values | Default |
159
159
  |---|---|---|
160
- | `brandPlacement` | `'sidebar'` (rail top) · `'topbar'` (top-left of the header, >= 768 px) | `'sidebar'` |
161
- | `sidebarWidth` | `'default'` 220 · `'sm'` 240 · `'md'` 264 · `'lg'` 288 px (`SIDEBAR_WIDTH_PX`) | `'default'` |
160
+ | `placement` | `'sidebar'` (rail top) · `'topbar'` (top-left of the header, >= 768 px, same background and bottom border as the top bar) | `'sidebar'` |
161
+ | `railWidth` | `'default'` 220 · `'sm'` 240 · `'md'` 264 · `'lg'` 288 px (`SIDEBAR_WIDTH_PX`) | `'default'` |
162
162
  | `drawerHeader` | `'none'` · `'brand'` (brand once in the open drawer's header, with a close button) | `'none'` |
163
163
  | `drawerWidth` | `'default'` (280 px panel + scrim) · `'full'` (whole screen, close button) | `'default'` |
164
164
 
165
165
  ```tsx
166
- <NavShell layout="side" brandPlacement="topbar" sidebarWidth="sm" drawerHeader="brand" drawerWidth="full"
166
+ <NavShell layout="side" brand={{ placement: 'topbar', railWidth: 'sm', drawerHeader: 'brand', drawerWidth: 'full' }}
167
167
  sideRail={{ items, title, brand: <AppBrand /> }} header={<Topbar ... />} {...rest} />
168
168
  ```
169
169
 
package/dist/index.d.mts CHANGED
@@ -53,10 +53,10 @@ type DrawerHeader = 'none' | 'brand';
53
53
  type DrawerWidth = 'default' | 'full';
54
54
  /** Pixel width of each named side-rail width token. */
55
55
  declare const SIDEBAR_WIDTH_PX: Readonly<Record<SidebarWidth, number>>;
56
- /** Shell brand and drawer options; each is one prop with a default that keeps today's layout. */
56
+ /** Fields of NavShell's one `brand` prop; each has a default that keeps today's layout. */
57
57
  interface NavBrandOptions {
58
- brandPlacement?: BrandPlacement;
59
- sidebarWidth?: SidebarWidth;
58
+ placement?: BrandPlacement;
59
+ railWidth?: SidebarWidth;
60
60
  drawerHeader?: DrawerHeader;
61
61
  drawerWidth?: DrawerWidth;
62
62
  }
@@ -175,8 +175,6 @@ interface SidebarProps {
175
175
  onNavigate: (route: string) => void;
176
176
  /** Localized menu title (heading); `null` leaves the slot empty. */
177
177
  title: React.ReactNode;
178
- /** Named rail width (default 220 px). */
179
- width?: SidebarWidth;
180
178
  /** Localized accessibility label for the navigation landmark. */
181
179
  regionLabel: string;
182
180
  /** a11y hint for a leaf item, given its label. Defaults to the label. */
@@ -215,7 +213,7 @@ interface SidebarProps {
215
213
  /** Extra container style overrides. */
216
214
  containerStyle?: ViewStyle | ViewStyle[];
217
215
  }
218
- declare const Sidebar: ({ items, pathname, onNavigate, title, width: railWidth, regionLabel, navigateHint, expandHint, collapseHint, renderChevron, enableInlineSearch, search, paletteTrigger, searchQuery, onSearchChange, header, footer, containerStyle, }: SidebarProps) => React.ReactElement;
216
+ declare const Sidebar: ({ items, pathname, onNavigate, title, regionLabel, navigateHint, expandHint, collapseHint, renderChevron, enableInlineSearch, search, paletteTrigger, searchQuery, onSearchChange, header, footer, containerStyle, }: SidebarProps) => React.ReactElement;
219
217
 
220
218
  /**
221
219
  * SidebarChevron — the built-in disclosure caret for an expandable sidebar
@@ -871,7 +869,9 @@ interface NavShellSideRail {
871
869
  * auth gate, state cards, banner, and width policy — passes through untouched.
872
870
  */
873
871
  type ForwardedShellProps = Omit<AppShellProps, 'header' | 'sidebar' | 'children'>;
874
- interface NavShellProps extends ForwardedShellProps, NavBrandOptions {
872
+ interface NavShellProps extends ForwardedShellProps {
873
+ /** Brand placement, rail width and phone drawer options; defaults keep today's layout. */
874
+ brand?: NavBrandOptions;
875
875
  /** Which regions to render: a top bar, a side rail, or both. */
876
876
  layout: NavShellLayout;
877
877
  /** Current active route/path — drives active highlighting on both regions. */
@@ -903,7 +903,7 @@ interface NavShellProps extends ForwardedShellProps, NavBrandOptions {
903
903
  sideRail?: NavShellSideRail;
904
904
  children: React.ReactNode;
905
905
  }
906
- declare const NavShell: ({ layout, pathname, onNavigate, regionLabel, navigateHint, topBar, header, sideRail, children, collapsedSidebar: collapsedSidebarProp, collapsedRailRange: collapsedRailRangeProp, brandPlacement, sidebarWidth, drawerHeader, drawerWidth, mobileMenu, ...shellProps }: NavShellProps) => React.ReactElement | null;
906
+ declare const NavShell: ({ layout, pathname, onNavigate, regionLabel, navigateHint, topBar, header, sideRail, children, collapsedSidebar: collapsedSidebarProp, collapsedRailRange: collapsedRailRangeProp, brand, mobileMenu, ...shellProps }: NavShellProps) => React.ReactElement | null;
907
907
 
908
908
  /**
909
909
  * CollapsedRail — the icon-only vertical rail for the intermediate (tablet) tier
package/dist/index.d.ts CHANGED
@@ -53,10 +53,10 @@ type DrawerHeader = 'none' | 'brand';
53
53
  type DrawerWidth = 'default' | 'full';
54
54
  /** Pixel width of each named side-rail width token. */
55
55
  declare const SIDEBAR_WIDTH_PX: Readonly<Record<SidebarWidth, number>>;
56
- /** Shell brand and drawer options; each is one prop with a default that keeps today's layout. */
56
+ /** Fields of NavShell's one `brand` prop; each has a default that keeps today's layout. */
57
57
  interface NavBrandOptions {
58
- brandPlacement?: BrandPlacement;
59
- sidebarWidth?: SidebarWidth;
58
+ placement?: BrandPlacement;
59
+ railWidth?: SidebarWidth;
60
60
  drawerHeader?: DrawerHeader;
61
61
  drawerWidth?: DrawerWidth;
62
62
  }
@@ -175,8 +175,6 @@ interface SidebarProps {
175
175
  onNavigate: (route: string) => void;
176
176
  /** Localized menu title (heading); `null` leaves the slot empty. */
177
177
  title: React.ReactNode;
178
- /** Named rail width (default 220 px). */
179
- width?: SidebarWidth;
180
178
  /** Localized accessibility label for the navigation landmark. */
181
179
  regionLabel: string;
182
180
  /** a11y hint for a leaf item, given its label. Defaults to the label. */
@@ -215,7 +213,7 @@ interface SidebarProps {
215
213
  /** Extra container style overrides. */
216
214
  containerStyle?: ViewStyle | ViewStyle[];
217
215
  }
218
- declare const Sidebar: ({ items, pathname, onNavigate, title, width: railWidth, regionLabel, navigateHint, expandHint, collapseHint, renderChevron, enableInlineSearch, search, paletteTrigger, searchQuery, onSearchChange, header, footer, containerStyle, }: SidebarProps) => React.ReactElement;
216
+ declare const Sidebar: ({ items, pathname, onNavigate, title, regionLabel, navigateHint, expandHint, collapseHint, renderChevron, enableInlineSearch, search, paletteTrigger, searchQuery, onSearchChange, header, footer, containerStyle, }: SidebarProps) => React.ReactElement;
219
217
 
220
218
  /**
221
219
  * SidebarChevron — the built-in disclosure caret for an expandable sidebar
@@ -871,7 +869,9 @@ interface NavShellSideRail {
871
869
  * auth gate, state cards, banner, and width policy — passes through untouched.
872
870
  */
873
871
  type ForwardedShellProps = Omit<AppShellProps, 'header' | 'sidebar' | 'children'>;
874
- interface NavShellProps extends ForwardedShellProps, NavBrandOptions {
872
+ interface NavShellProps extends ForwardedShellProps {
873
+ /** Brand placement, rail width and phone drawer options; defaults keep today's layout. */
874
+ brand?: NavBrandOptions;
875
875
  /** Which regions to render: a top bar, a side rail, or both. */
876
876
  layout: NavShellLayout;
877
877
  /** Current active route/path — drives active highlighting on both regions. */
@@ -903,7 +903,7 @@ interface NavShellProps extends ForwardedShellProps, NavBrandOptions {
903
903
  sideRail?: NavShellSideRail;
904
904
  children: React.ReactNode;
905
905
  }
906
- declare const NavShell: ({ layout, pathname, onNavigate, regionLabel, navigateHint, topBar, header, sideRail, children, collapsedSidebar: collapsedSidebarProp, collapsedRailRange: collapsedRailRangeProp, brandPlacement, sidebarWidth, drawerHeader, drawerWidth, mobileMenu, ...shellProps }: NavShellProps) => React.ReactElement | null;
906
+ declare const NavShell: ({ layout, pathname, onNavigate, regionLabel, navigateHint, topBar, header, sideRail, children, collapsedSidebar: collapsedSidebarProp, collapsedRailRange: collapsedRailRangeProp, brand, mobileMenu, ...shellProps }: NavShellProps) => React.ReactElement | null;
907
907
 
908
908
  /**
909
909
  * CollapsedRail — the icon-only vertical rail for the intermediate (tablet) tier
package/dist/index.js CHANGED
@@ -845,8 +845,8 @@ var SIDEBAR_WIDTH_PX = {
845
845
  lg: 288
846
846
  };
847
847
  var NAV_BRAND_DEFAULTS = {
848
- brandPlacement: "sidebar",
849
- sidebarWidth: "default",
848
+ placement: "sidebar",
849
+ railWidth: "default",
850
850
  drawerHeader: "none",
851
851
  drawerWidth: "default"
852
852
  };
@@ -867,7 +867,6 @@ var Sidebar = ({
867
867
  pathname,
868
868
  onNavigate,
869
869
  title,
870
- width: railWidth = "default",
871
870
  regionLabel,
872
871
  navigateHint = (label) => label,
873
872
  expandHint = "",
@@ -915,7 +914,7 @@ var Sidebar = ({
915
914
  role: "navigation",
916
915
  style: [
917
916
  navStyles.sidebarContainer,
918
- { width: SIDEBAR_WIDTH_PX[railWidth] },
917
+ { width: SIDEBAR_WIDTH_PX.default },
919
918
  { backgroundColor: colors.surface, borderRightColor: colors.border },
920
919
  containerStyle
921
920
  ],
@@ -2194,7 +2193,7 @@ function renderShellSidebar({ sideRail, nav, width, showBrand }) {
2194
2193
  Sidebar,
2195
2194
  {
2196
2195
  collapseHint: sideRail.collapseHint,
2197
- containerStyle: sideRail.containerStyle,
2196
+ containerStyle: { width: SIDEBAR_WIDTH_PX[width], ...reactNative.StyleSheet.flatten(sideRail.containerStyle) },
2198
2197
  enableInlineSearch: sideRail.enableInlineSearch,
2199
2198
  expandHint: sideRail.expandHint,
2200
2199
  footer: sideRail.footer,
@@ -2208,7 +2207,6 @@ function renderShellSidebar({ sideRail, nav, width, showBrand }) {
2208
2207
  search: sideRail.search,
2209
2208
  searchQuery: sideRail.searchQuery,
2210
2209
  title: showBrand ? brandSlot : null,
2211
- width,
2212
2210
  onNavigate: nav.onNavigate,
2213
2211
  onSearchChange: sideRail.onSearchChange
2214
2212
  }
@@ -2216,14 +2214,15 @@ function renderShellSidebar({ sideRail, nav, width, showBrand }) {
2216
2214
  }
2217
2215
  var styles11 = reactNative.StyleSheet.create({
2218
2216
  row: { flexDirection: "row", alignItems: "center" },
2219
- brand: { justifyContent: "center", paddingHorizontal: 12 },
2217
+ brand: { justifyContent: "center", alignSelf: "stretch", paddingHorizontal: 12, borderBottomWidth: 1 },
2220
2218
  fill: { flex: 1 }
2221
2219
  });
2222
2220
  var TopbarBrandRow = ({ brand, brandWidth, testID, children }) => {
2223
2221
  const { width } = reactNative.useWindowDimensions();
2222
+ const { colors } = uiFeedback.useUi().theme;
2224
2223
  if (width < RAIL_FULL_BREAKPOINT) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
2225
2224
  return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles11.row, testID, children: [
2226
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles11.brand, brandWidth !== void 0 ? { width: brandWidth } : null], testID: `${testID}-brand`, children: brand }),
2225
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles11.brand, { backgroundColor: colors.background, borderBottomColor: colors.border }, brandWidth !== void 0 ? { width: brandWidth } : null], testID: `${testID}-brand`, children: brand }),
2227
2226
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles11.fill, children })
2228
2227
  ] });
2229
2228
  };
@@ -2245,10 +2244,7 @@ var NavShell = ({
2245
2244
  children,
2246
2245
  collapsedSidebar: collapsedSidebarProp,
2247
2246
  collapsedRailRange: collapsedRailRangeProp,
2248
- brandPlacement = NAV_BRAND_DEFAULTS.brandPlacement,
2249
- sidebarWidth = NAV_BRAND_DEFAULTS.sidebarWidth,
2250
- drawerHeader = NAV_BRAND_DEFAULTS.drawerHeader,
2251
- drawerWidth = NAV_BRAND_DEFAULTS.drawerWidth,
2247
+ brand,
2252
2248
  mobileMenu,
2253
2249
  ...shellProps
2254
2250
  }) => {
@@ -2277,11 +2273,12 @@ var NavShell = ({
2277
2273
  ) : null;
2278
2274
  const nav = { pathname, onNavigate, regionLabel, navigateHint };
2279
2275
  const rail = showSideRail ? sideRail : void 0;
2280
- const brandInBar = brandPlacement === "topbar" && rail?.brand !== void 0;
2276
+ const { placement, railWidth, drawerHeader, drawerWidth } = { ...NAV_BRAND_DEFAULTS, ...brand };
2277
+ const brandInBar = placement === "topbar" && rail?.brand !== void 0;
2281
2278
  const brandInDrawer = drawerHeader === "brand" ? rail?.brand : void 0;
2282
- const sidebarNode = rail === void 0 ? void 0 : renderShellSidebar({ sideRail: rail, nav, width: sidebarWidth, showBrand: !brandInBar });
2283
- const drawerSidebar = rail !== void 0 && brandInDrawer !== void 0 && !brandInBar ? renderShellSidebar({ sideRail: rail, nav, width: sidebarWidth, showBrand: false }) : void 0;
2284
- const shellHeader = brandInBar ? /* @__PURE__ */ jsxRuntime.jsx(TopbarBrandRow, { brand: rail?.brand, brandWidth: SIDEBAR_WIDTH_PX[sidebarWidth], testID: `${shellProps.testID}-topbar-brand-row`, children: headerNode }) : headerNode;
2279
+ const sidebarNode = rail === void 0 ? void 0 : renderShellSidebar({ sideRail: rail, nav, width: railWidth, showBrand: !brandInBar });
2280
+ const drawerSidebar = rail !== void 0 && brandInDrawer !== void 0 && !brandInBar ? renderShellSidebar({ sideRail: rail, nav, width: railWidth, showBrand: false }) : void 0;
2281
+ const shellHeader = brandInBar ? /* @__PURE__ */ jsxRuntime.jsx(TopbarBrandRow, { brand: rail?.brand, brandWidth: SIDEBAR_WIDTH_PX[railWidth], testID: `${shellProps.testID}-topbar-brand-row`, children: headerNode }) : headerNode;
2285
2282
  const collapsedCfg = showSideRail ? sideRail?.collapsed : void 0;
2286
2283
  const collapsedNode = collapsedCfg !== void 0 && sideRail !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2287
2284
  CollapsedRail,