import ContextDefinition from 'terra-disclosure-manager/lib/DisclosureManagerContext?dev-site-codeblock';

# DisclosureManagerContext

The DisclosureManagerContext defines an communication interface between the ModalManager/SlidePanelManager and application content.

> Note: A DisclosureManagerContext.Provider is rendered by the ModalManager and SlidePanelManager. Any components rendered within
> those managers (or disclosed by them) can access a DisclosureManagerContext value without rendering additional providers.

## Usage

```jsx
import { DisclosureManagerContext } from 'terra-application/lib/disclosure-manager';
```

## Context Value

<ContextDefinition />

## Details

### DisclosureManagerHeaderAdapter

Implementations of the DisclosureManager must render a header containing controls for the various disclosure management actions
(close, back, maximize/minimize, etc.). The DisclosureManagerHeaderAdapter can be rendered by the disclosed content to inject
their own component-specific contents into that header.

`DisclosureManagerHeaderAdapter` Props:

|Prop|Is Required|Description|
|---|---|---|
|`title`|optional|A string to render as the header's title.|
|`collapsibleMenuView`|optional|A CollapsibleMenuView component to render within the header.|

```jsx
import { DisclosureManagerContext, DisclosureManagerHeaderAdapter } from 'terra-application/lib/disclosure-manager';
import CollapsibleMenuView from 'terra-collapsible-menu-view';

const MyDisclosureComponent = () => {
  const disclosureManager = React.useContext(DisclosureManagerContext);

  return (
    <React.Fragment>
      <DisclosureManagerHeaderAdapter
        title="My Disclosure Component"
        collapsibleMenuView={<CollapsibleMenuView ... />}
      />
      <Button
        text="Close Modal"
        onClick={() => {
          disclosureManager.closeDisclosure();
        }}
      />
    </React.Fragment>
  );
};
```

### Children

The DisclosureManagerDelegate provided to the child components contains a `disclose` function. This `disclose` function
validates the disclosure type with which it is provided against the set of supported disclosure types given to the DisclosureManager
as a prop. If the provided type is not supported, and if the DisclosureManager detects another DisclosureManager higher in the
component hierarchy, the DisclosureManager will call the disclose function provided by that parent DisclosureManager instance.

If the type is supported, the DisclosureManager will check the currently disclosed component's state to ensure it can be replaced.
If the disclosure is denied, then `disclose` returns a rejected Promise. If the disclosure is allowed, then a resolved Promise is returned.
This Promise will be resolved with an Object containing functions and Promises that can be used to manipulate the disclosure, if necessary.
Included are `dismissDisclosure`, a function that will dismiss the disclosed content, and `afterDismiss`, a deferred Promise that will be
resolved when the disclosed content is dismissed by any means. Alternatively, if the additional logic isn't needed, the returned Promise
can be completely ignored.

Example:
```jsx
disclosureManager.disclose({
  preferredType: 'disclosure-type',
  size: 'large',
  content: {
    key: 'my-disclosed-content',
    component: <DisclosedContent />,
  }
}).then({ dismissDisclosure, afterDismiss } => {
  this.myContentIsDisclosed = true;

  // This function can be cached and triggered as needed.
  this.myDismissFunction = dismissDisclosure;

  afterDismiss.then(() => {
    // The afterDismiss will resolve when the content is dismissed, allowing for
    // cleanup of local state as needed.
    this.myContentIsDisclosed = false;

    // If the dismissDisclosure function was cached, make sure it gets cleaned up.
    this.myDismissFunction = false;
  })
}).catch((e) => {
  // If this function is executed, the disclosure has been denied. You can use this to
  // clean up any state that may be reliant on the disclosure ocurring.
})
```

`disclose` Argument API:

|Key|Is Required|Value|
|---|---|---|
|`preferredType`|optional|The String describing the preferred disclosure type. This will be used to match the disclosure request to an appropriate DisclosureManager. Depending on the structuring of managers in a given component, the `preferredType` value may not be honored. If the provided `preferredType` is not supported by any present disclosure managers, the root disclosure manager will perform the disclosure using its own disclosure type, regardless of the `preferredType` value.|
|`size`|optional|The String size desired for the disclosure. One of `tiny`, `small`, `medium`, `large`, `huge`, or `fullscreen`. The functional implementation of this size is determined by the rendering component. `size` should not be provided if `dimensions` are specified.|
|`dimensions`|optional|An Object containing explicit `height` and `width` values for the disclosure. These values may not be honored due to the disclosure type or the available viewport size. `dimensions` should not be provided if a `size` is specified.<br />Supported `height` values include: `'240'`, `'420'`, `'600'`, `'690'`, `'780'`, `'870'`, `'960'`, `'1140'`.<br />Supported `width` values include: `'320'`, `'480'`, `'560'`, `'640'`, `'800'`, `'960'`, `'1120'`, `'1280'`, `'1440'`, `'1600'`, `'1760'`, `'1920'`.|
|`content`|**required**|An Object containing a key and a component describing the component to be disclosed. See the `content` API below.|

`content` Object API:

|Key|Is Required|Value|
|---|---|---|
|`key`|**required**|A String key identifying the component to the DisclosureManager. This key must be unique amongst the set of all actively disclosed component keys.|
|`component`|**required**|A React element that will be disclosed.|

### Disclosure Content

In addition to a `disclose` function, a number of other functions are exposed to components rendered in the disclosure mechanism to manage various segments of the disclosure state. The included functions are:

|Function|Description|
|---|---|
|`disclose`|Allows a component to disclose another component. See above for argument API. The DisclosureManager implementation will determine how the next object will be disclosed.|
|`dismiss`|Allows a component to remove itself from the disclosure stack. If the component is the only element in the disclosure stack, the disclosure is closed.|
|`closeDisclosure`|Allows a component to close the entire disclosure stack. This is generally integrated into face-up disclosure controls as a Close button or similar.|
|`goBack`|Allows a component to remove itself from the disclosure stack. Functionally similar to `dismiss`, however `onBack` is only provided to components in the stack that have a previous sibling. This is generally integrated into face-up disclosure controls as a Back button or similar.|
|`maximize`|Allows a component to maximize its presentation size. This is only provided if the component is not already maximized.|
|`minimize`|Allows a component to minimize its presentation size. This is only provided if the component is currently maximized.|
|`requestFocus`|Allows a component to request focus from the disclosure in the event that the disclosure mechanism in use utilizes a focus trap. This can be integrated with the Popup and similar focus-stealing controls.|
|`releaseFocus`|Allows a component to release focus from itself and return it to the disclosure. This can be integrated with the Popup and similar focus-stealing controls.|
|`registerDismissCheck`|Allows a component to register a function with the DisclosureManager that will be called before the component is dismissed. Calling this function will override the default implementation that checks for the presence of NavigationPrompts.|

Each of these functions returns a Promise that can be used for chaining, if necessary.

#### A Note on `registerDismissCheck`

By default, the DisclosureManager monitors its disclosed content for the presence of [NavigationPrompts](/application/terra-application/components/navigation-prompt).
The user will be prompted if they attempt to close the dismiss the disclosure while NavigationPrompts are present.

If the modal content calls `registerDismissCheck` to add its own pre-dismissal logic, the default NavigationPrompt handling will be **disabled**.
Any component that uses `registerDismissCheck` should check for the presence of NavigationPrompts (using a [NavigationPromptCheckpoint](/application/terra-application/components/navigation-prompt-checkpoint))
in addition to whatever custom logic is required.

Given this complexity, usage of the `registerDismissCheck` API is **not recommended**.

The function provided to `registerDismissCheck` must return a resolved or rejected Promise.
If the Promise is resolved, the component is guaranteed to be dismissed.
If cleanup logic needs to execute before the component is dismissed, it is a good idea to execute before returning the resolved Promise.
If a rejected Promise is returned, the component will not be dismissed.
