import PropsTable from 'terra-application/lib/application-navigation/ApplicationNavigation?dev-site-props-table';
import ApplicationNavigationWorkspaceProps from 'terra-application/lib/application-navigation/private/workspace-layout/ApplicationNavigationWorkspace?dev-site-props-table';

import ApplicationNavigationExample from './example/ApplicationNavigationExample?dev-site-example';
import ApplicationNavigationWorkspaceExample from './example/ApplicationNavigationWorkspaceExample?dev-site-example';

import { Notice } from '@cerner/terra-docs';

# ApplicationNavigation

The ApplicationNavigation component provides a styled layout and controls used for navigating within an application.

## Usage

```jsx
import ApplicationNavigation from 'terra-application/lib/application-navigation';
```

## Required Contexts

ApplicationNavigation requires values from the following Contexts:

* [ApplicationIntlContext](/application/terra-application/contexts/application-intl-context)

## Props

<PropsTable />

### `extensionItems`
#### Is Required: `false`

The `extensionItems` prop allows consumers to render icons with an associated selection callback within the ApplicationNavigation's extensions region.
The expectations for `extensionItems` is that they are to provide click actions and disclosures for the application level context. The `extensionItems` will
rollup in various counts depending on the current breakpoint. If `extensionItems` are passed as props the associated `onSelectExtensionItem` function callback
should be passed as well.

The value provided for `extensionItems` should be an array of objects with the following API:

|Key Name|Type|Is Required|Description|
|---|---|---|---|
|`key`|String|**required**|A key rendered to be used as a unique react key as well as returned with the onSelectExtensionItem.|
|`icon`|Element|**required**|A React element representing the themable icon for the extension.|
|`text`|String|**required**|The text to either be set as an aria-label or display text.|
|`metaData`|Object|optional|An object containing whatever additional identifying information to be returned with the onSelectExtensionItem.|

```jsx
const extensionItems = [{
  key: 'extension_1',
  icon: <Icon1 >,
  text: 'Extension 1',
  metaData: { myValue: value1 }
}, {
  key: 'extension_2',
  icon: <Icon2 >,
  text: 'Extension 2',
  metaData: { myValue: value2 }
}];
```

### `onSelectExtensionItem`
#### Is Required: `false`

The `onSelectExtensionItem` prop allows consumers to retrieve the information related to the extension that was clicked.
The function callback will return the information in the format of `onSelectExtensionItem(key, metaData)`.

### `navigationItems`
#### Is Required: `false`

The `navigationItems` prop allows consumers to render high-level, primary navigation controls directly within the ApplicationNavigation.
The expectation of `navigationItems` is that items will not be added/removed, as this would be detrimental to the user experience.
 Once selected, a navigational item is no longer actionable and cannot be reselected. Navigation items at the application level should
 have equivalent context levels. Navigation from one tab to another should not be influenced by content, as each navigational item should be a sandboxed concept.

The ApplicationNavigation will render this content in different ways based on the active responsive breakpoint.
If `navigationItems` are passed as props the associated `onSelectNavigationItem` function callback should be passed as well.

The value provided for `navigationItems` should be an array of objects with the following API:

|Key Name|Type|Is Required|Description|
|---|---|---|---|
|`key`|String|**required**|A key rendered to be used as a unique react key as well as returned with the onSelectNavigationItem.|
|`text`|String|**required**|The text to either be set as an aria-label or display text.|
|`metaData`|Object|optional|An object containing whatever additional identifying information to be returned with the onSelectNavigationItem.|

```jsx
const navigationItems = [{
  key: 'page_1',
  text: 'Page 1',
  metaData: { myValue: value1 }
}, {
  key: 'page_2',
  text: 'Page 2',
  metaData: { myValue: value2 }
}];
```

### `onSelectNavigationItem`
#### Is Required: `false`

The `onSelectNavigationItem` prop allows consumers to retrieve the information related to the navigation item that was clicked.
The function callback will return the information in the format of `onSelectNavigationItem(key, metaData)`.

### `activeNavigationItemKey`
#### Is Required: `false`

The `activeNavigationItemKey` prop allows consumers to set the currently selected navigation item.
Accordingly, the `activeNavigationItemKey` value must have an associated entry within the `navigationItems` specification.

### `utilityItems`
#### Is Required: `false`

The `utilityItems` prop allows consuming applications to present an application-level custom utility items directly from the ApplicationNavigation.
The ApplicationNavigation will render this content in different ways based on the active responsive breakpoint. If `utilityItems` are
passed as props the associated `onSelectUtilityItem` function callback should be passed as well.

The value provided for `utilityItems` should be an array of objects with the following API:

|Key Name|Type|Is Required|Description|
|---|---|---|---|
|`key`|String|**required**|A key rendered to be used as a unique react key as well as returned with the onSelectUtilityItem.|
|`icon`|Element|**required**|A React element representing the themable icon for the utility item.|
|`text`|String|**required**|The text to either be set as an aria-label or display text.|
|`metaData`|Object|optional|An object containing whatever additional identifying information to be returned with the onSelectUtilityItem.|

```jsx
const utilityItems = [{
  key: 'utility_1',
  icon: <Icon1 >,
  text: 'Utility 1',
  metaData: { myValue: value1 }
}, {
  key: 'utility_2',
  icon: <Icon2 >,
  text: 'Utility 2',
  metaData: { myValue: value2 }
}];
```

### `onSelectUtilityItem`
#### Is Required: `false`

The `onSelectUtilityItem` prop allows consumers to retrieve the information related to the navigation item that was clicked.
The function callback will return the information in the format of `onSelectUtilityItem(key, metaData)`.

### `onSelectSettings`
#### Is Required: `false`

The `onSelectSettings` prop allows consumers have first class support for a settings utility item.
If the `onSelectSettings` prop is not set a settings utility item will not be displayed.

### `onSelectHelp`
#### Is Required: `false`

The `onSelectHelp` prop allows consumers have first class support for a help utility item.
If the `onSelectHelp` prop is not set a settings utility item will not be displayed.

### `onSelectLogout`
#### Is Required: `false`

The `onSelectLogout` prop allows consumers have first class support for a logout utility button.
If the `onSelectLogout` prop is not set a settings utility item will not be displayed.

### `titleConfig`
#### Is Required: `false`

The `titleConfig` prop allows consuming applications to add their own branding to the ApplicationNavigation.
The ApplicationNavigation will render this content in different ways based on the active responsive breakpoint.

|Key Name|Type|Is Required|Description|
|---|---|---|---|
|`title`|String|**required**|Title to be displayed or set as the aria-label if a title element is passed.
|`headline`|String|optional|Super text to be display above the main title text.|
|`subline`|String|optional|Sub text to be display below the main title text.
|`element`|Element|optional|Element to use in place of title text. Typically a logo for branding.
|`hideTitleWithinDrawerMenu`|Boolean|optional|Whether or not the title should be hidden when at the compact breakpoint.|

```jsx
const myTitleConfig = {
  title: 'My Application',
  subline: 'My Subline',
  hideTitleWithinDrawerMenu: false,
}
```

### `userConfig`
#### Is Required: `false`

The `userConfig` prop allows consumers to set a user associated to the current application context.
The ApplicationNavigation will render this content in different ways based on the active responsive breakpoint.

<Notice ariaLevel="5">

It is recommended that `initials` prop be provided for all cases if `userConfig` is used. It will be updated to **Required** with the next major version of application navigation, provided via terra-application v2.

*Note: If both `initials` and `imageSrc` are not provided, the avatar will fall back to the generic user avatar. If `initials` are not provided, but `imageSrc` is provided and fails, the avatar will fall back to use first two letters of the provided `name` (not preferred) in place of showing the `initials` (preferred).*

</Notice>

|Key Name|Type|Is Required|Description|
|---|---|---|---|
|`name`|String|**required**|User name to be displayed for the user button and within utilities.
|`detail`|String|optional|Additional user details string.|
|`initials`|String|optional|User initials to be displayed within the avatar if no image is present.
|`imageSrc`|String|optional|Src to provide to the avatar component.|

```jsx
const myUserConfig = {
  name: 'Name, User',
  detail: 'DomainName123',
  initials: 'UN',
  imageSrc: 'imageSrc',
}
```

### `userActionConfig`
#### Is Required: `false`

The `userActionConfig` prop allows consumers to add an additional item to the `userConfig` section where it is displayed within the application. If a specific action related to a User's information or details, consumers can use this prop which will add a button along with the user name, detail, and avatar. Note: if the `userConfig` prop is not set, the user action button will not be displayed.

|Key Name|Type|Is Required|Description|
|---|---|---|---|
|`text`|String|**required**|Text to be displayed on user action button.
|`userActionCallback`|Function|**required**|A function to be executed on user action button click.|

```jsx
const userActionConfig = {
  text: 'User Specific Action',
  userActionCallback: () => console.log('Button Clicked'),
};
```

### `hero`
#### Is Required: `false`

The `hero` prop allows consumers to add a hero element within the utility popup and/or navigation drawer.
The ApplicationNavigation will render this content in different ways based on the active responsive breakpoint.

### `notifications`
#### Is Required: `false`

The `notifications` prop allows consumers to display notification counts associated to navigationItems and extensionsItems.
The props is made up of key/value pairs; the key is the associated entry within the `navigationItems` or `extensionItems` specification,
and a numerical value. Depending on locations within the navigational structure and breakpoint the number of digits displayed may be limited.

```jsx
const myNotifications = {
  key1: 3,
  extension2: 10,
}
```

### `onDrawerMenuStateChange`
#### Is Required: `false`

`onDrawerMenuStateChange` callback allows the consumer to know state changes in Drawer Menu.

### `workspace`
#### Is Required: `false`

The `workspace` prop allows consumers to render a persistent aside region within the layout.

<Notice ariaLevel="5">

Only an instance of the `ApplicationNavigation.Workspace` component may be supplied to the `workspace` prop.

</Notice>

<Notice variant="caution" ariaLevel="5">

If a workspace is rendered by the ApplicationNavigation component, children of the component must use the [ApplicationNavigationActionsContext](/application/terra-application/contexts/application-navigation-actions-context)
to render the action controls necessary for its usage. Failure to do so will lead to a lack of user control over the workspace and an inconsistent user experience.

</Notice>

## Subcomponents

### ApplicationNavigation.Workspace

The `ApplicationNavigation.Workspace` component defines the interface for presenting content within the ApplicationNavigation's workspace region.

#### Props

<ApplicationNavigationWorkspaceProps />

### ApplicationNavigation.Workspace.Item

The `ApplicationNavigation.Workspace.Item` defines the labeling of a tab within the workspace region as well as its associated content.

#### Props

|Prop Name|Type|Is Required|Default Value|Description|
|---|---|---|---|---|
|`itemKey`|string|<span style={{ color: '#d53040' }}>**required**</span>|none|A unique key used to identify the item. Must be unique within the collection of provided items.|
|`label`|string|<span style={{ color: '#d53040' }}>**required**</span>|none|A string used to visibly label the content within the workspace.|
|`metaData`|object|optional|none|Additional data that will be returned with callbacks from the workspace component.|
|`render`|func|optional|none|A function executed during rendering to generate content for the item.|

## Responsive Design

The ApplicationNavigation has two rendering modes: `standard` and `compact`.
  - The `standard` rendering occurs at `large`, `huge`, and `enormous` breakpoints.
  - The `compact` rendering occurs at `tiny`, `small`, `medium` breakpoints.

|Prop|`standard` Rendering|`compact` Rendering|
|---|---|---|
|`userConfig`|Content is rendered within ApplicationNavigation's header.|Content is rendered within ApplicationNavigation's navigation drawer.|
|`titleConfig`|Content is rendered within ApplicationNavigation's header.|Same as `standard`.|
|`hero`|Content is rendered within ApplicationNavigation's utility popup (as provided by `terra-popup`).|Content is rendered within ApplicationNavigation's navigation drawer.|
|`utilityItems`|Content is rendered within ApplicationNavigation's utility popup (as provided by `terra-popup`).|Content is rendered within ApplicationNavigation's navigation drawer.|
|`navigationItems`|Content is rendered within the ApplicationNavigation's header as tabs.|Content is rendered within ApplicationNavigation's navigation drawer.|
|`extensionItems`|Content is rendered within ApplicationNavigation's header.|Same as `standard`.|
|`userActionConfig`|Content is rendered within ApplicationNavigation's utility popup (as provided by `terra-popup`).|Content is rendered within ApplicationNavigation's navigation drawer.|

## Example

<ApplicationNavigationExample />

<ApplicationNavigationWorkspaceExample />

## Features

### Exception Handling

ApplicationNavigation renders an [ApplicationErrorBoundary](/application/terra-application/components/application-error-boundary) around its children.
If the children throw exceptions during React lifecycle functions, ApplicationBase will catch the exceptions and render a styled error component in place of the children.

This error component will render below ApplicationNavigation's header, leaving the user with full access to all navigation controls after an error occurs.

### Loading Overlays

ApplicationNavigation renders an [ApplicationLoadingOverlayProvider](/application/terra-application/components/application-loading-overlay-provider) around its children.
Any [ApplicationLoadingOverlay](/application/terra-application/components/application-loading-overlay) components rendered by children will cause a loading overlay
to be presented over ApplicationNavigation's children.

The loading overlay will render below ApplicationNavigation's header, leaving the user with full access to all navigation controls while the loading overlay is presented.

### Status Views

ApplicationNavigation renders an [ApplicationStatusOverlayProvider](/application/terra-application/components/application-status-overlay-provider) around its children.
Any [ApplicationStatusOverlay](/application/terra-application/components/application-status-overlay) components rendered by children will cause a status view
to be presented over ApplicationNavigation's children.

The status view will render below ApplicationNavigation's header, leaving the user with full access to all navigation controls while the status view is presented.

### Unsaved Changes

ApplicationNavigation monitors its children for the presence of rendered [NavigationPrompts](/application/terra-application/components/navigation-prompt)
by rendering a [NavigationPromptCheckpoint](/application/terra-application/components/navigation-prompt-checkpoint) around its children.
ApplicationNavigation will ensure that the user is prompted when a primary navigation or 'Logout' utility selection is made if any NavigationPrompts have
been rendered by children at the time of the selection.

If the children within ApplicationNavigation can be changed by a mechanism other than navigation item selection, a NavigationPromptCheckpoint should be used directly to
check for unsaved changes prior to the pending child's removal.

> Note: This default prompting can be disabled with the `disablePromptsForNavigationItems` and `disablePromptsForLogout` props if a custom implementation is required.

### Code Splitting

ApplicationNavigation renders a [Suspense](https://reactjs.org/docs/code-splitting.html#reactlazy) component around its children. If any child components or their
descendants are lazy loaded using [React.lazy](https://reactjs.org/docs/code-splitting.html#reactlazy), an ApplicationLoadingOverlay will be rendered while the component
is being retrieved. The overlay will render below the ApplicationNavigation header and allow the header to remain interactive.
