import * as React from 'react'; /** * What the shell's sidebar renders. * * These are deliberately **not** the same types as `NavLinkSpec` in * `@exxatdesignux/product-framework`. A spec is the serializable form a product * authors and a store round-trips; these are the resolved form the renderer * consumes, where an icon is already a React node and a drill-in may carry a * matcher function. `navLayoutToJsx()` turns the former into the latter. * * They live here rather than in the app because the shell renders them, and a * type owned by the app is a type the package cannot name in its own props. */ /** * A row that leads INTO a deep section: the sidebar content area swaps to a * stacked `[← Back] · · ` view while the URL matches. * * Mutually exclusive with {@link NavLinkItem.secondaryPanel} — a row either * drills in (the user goes *into* a section) or scopes a hub (the user narrows * what a hub lists), never both. */ interface NavDrillInConfig { /** Heading above the drilled-in list. */ sectionTitle: string; /** Pathname prefix that activates the view (e.g. `"/settings"`). */ sectionRouteRoot: string; /** * Matcher for sections whose URL embeds the product slug, which * `sectionRouteRoot` alone cannot express (`//leo`). Overrides the * default `startsWith(sectionRouteRoot)` check when set. */ sectionRouteMatch?: (pathname: string) => boolean; /** * Rows inside the drilled-in pane. Ignored when the section renders a slotted * body instead of a list. */ items: NavLinkItem[]; } /** One labelled group of primary rows. */ interface NavSection { key: string; /** Omit or leave empty to render the rows without a heading. */ label: string; items: NavLinkItem[]; } /** A product's whole primary nav: ungrouped rows, labelled groups, trailing rows. */ interface NavPrimaryLayout { preamble: NavLinkItem[]; sections: NavSection[]; /** Rows after every section, not grouped under a label. */ epilogue?: NavLinkItem[]; } /** A sidebar row: primary nav, Resources, or a utility group. */ interface NavLinkItem { key: string; title: string; url: string; icon: React.ReactNode; /** Filled variant shown while the row is the current destination. */ iconActive?: React.ReactNode; /** Present children render the row as a collapsible sub-menu. */ children?: NavLinkItem[]; /** * Inline count or label. `"New"` renders green and `"Beta"` amber; any other * string takes the brand colour. */ badge?: number | string; /** * Panel id when this section scopes a hub through the secondary rail. Child * rows use it to reopen the rail while already on the same route, which a * router `Link` will not do on its own. */ secondaryPanel?: string; /** * Set when the row leads into a deep section. The row's own `url` must land * inside `drillIn.sectionRouteRoot` so the pane shows on first navigation. */ drillIn?: NavDrillInConfig; /** * When several children share the parent's hub `url`, only this child is * highlighted for it. Without it every child row matching that href looks * selected at once. */ primaryHubChildKey?: string; } /** A quick-action or footer utility row. Unlike a primary row it can open UI instead of navigating. */ interface NavSecondaryItem { key: string; title: string; url: string; icon: React.ReactNode; /** Filled variant while active, matching primary rows. */ iconActive?: React.ReactNode; /** Opens the global command menu rather than navigating. */ opensCommandMenu?: boolean; /** Opens the assistant panel rather than navigating. */ opensAskLeo?: boolean; /** App-owned active-state refinement for routes the row URL cannot express. */ isActive?: (pathname: string) => boolean; /** Swaps the sidebar to a drilled-in stack while the URL matches. */ drillIn?: NavDrillInConfig; } /** The person the identity menu names. */ interface NavUserIdentity { name: string; email: string; avatar: string; } export type { NavDrillInConfig, NavLinkItem, NavPrimaryLayout, NavSecondaryItem, NavSection, NavUserIdentity };