{/* prettier-ignore */}
{/*
Copyright 2023 Comcast Cable Communications Management, LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

SPDX-License-Identifier: Apache-2.0
\*/}

import { Meta, Title } from '@storybook/blocks';
import { DocsLink } from '../../docs/utils';
import * as NavigationManagerStories from './NavigationManager.stories';

<Meta of={NavigationManagerStories} />

<Title />

NavigationManager is a subclass of [FocusManager](?path=/docs/components-focusmanager--docs),
and parent class of [Row](?path=/docs/components-row--docs) and [Column](?path=/docs/components-column--docs).
It contains shared properties and methods primarily concerned with scrolling and layout.

## Source

https://github.com/rdkcentral/Lightning-UI-Components/blob/develop/packages/@lightningjs/ui-components/src/components/NavigationManager/NavigationManager.js

## Usage

NavigationManager can be extended to create components that require scrolling logic.

```js
import { NavigationManager } from '@lightningjs/ui-components';

class CustomRow extends NavigationManager {}
```

### Scrolling

The `scrollIndex` property determines the index at which scrolling should begin. By default, that index is 0.
Scroll behavior is determined based on what is passed to the `alwaysScroll` and `neverScroll` properties.
If both of those properties are enabled, `alwaysScroll` will take precedence over `neverScroll`.

### directionProps

NavigationManager uses a constant, `directionPropNames`, to map property names from the
`direction` propety set in [FocusManager](?path=/docs/components-focusmanager--row). The properties it maps to are as follows:

```js
const directionPropNames = {
  row: {
    axis: 'x',
    crossAxis: 'y',
    lengthDimension: 'w',
    crossDimension: 'h',
    innerCrossDimension: 'innerH'
  },
  column: {
    axis: 'y',
    crossAxis: 'x',
    lengthDimension: 'h',
    crossDimension: 'w',
    innerCrossDimension: 'innerW'
  }
};
```

## API

### Properties

| name              | type    | required | default   | description                                                                                                                                                                                                                                                                    |
| ----------------- | ------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| alwaysScroll      | boolean | false    | false     | determines whether the component will stop scrolling as it nears the end to prevent white space                                                                                                                                                                                |
| autoResizeHeight  | boolean | false    | false     | automatically sets the height of the row to be the same as the Items container inside                                                                                                                                                                                          |
| autoResizeWidth   | boolean | false    | false     | automatically sets the width of the row to be the same as the Items container inside (this will prevent scrolling)                                                                                                                                                             |
| lazyUpCount       | number  | false    | undefined | If set, this is used to calculate the initial number of items to display on the first render (`lazyUpCount` + `lazyLoadUpCountBuffer`). The remaining items are stored as lazy items. Each time the user navigates further, the next lazy item will be added.                  |
| lazyUpCountBuffer | number  | false    | 2         | If `lazyUpCount` is set, this is used to calculate the initial number of items to display on the first render (`lazyUpCount` + `lazyLoadUpCountBuffer`). The remaining items are stored as lazy items. Each time the user navigates further, the next lazy item will be added. |
| neverScroll       | boolean | false    | false     | if true, the component will never scroll, unless alwaysScroll is set to true, and if false, the component will apply normal scrolling logic                                                                                                                                    |
| scrollIndex       | number  | false    | 0         | Item index at which scrolling begins, provided the sum of item widths is greater than the width of the `Row`                                                                                                                                                                   |
| waitForDimensions | boolean | false    | false     | if true, the `NavigationManager` will wait for all child elements' `w` and `h` to be set before displaying the `NavigationManager`                                                                                                                                             |

### Style Properties

| name           | type                             | description                                 |
| -------------- | -------------------------------- | ------------------------------------------- |
| alwaysScroll   | boolean                          | [See Properties section above](#properties) |
| neverScroll    | boolean                          | [See Properties section above](#properties) |
| scrollIndex    | number                           | [See Properties section above](#properties) |
| itemSpacing    | number                           | spacing between items                       |
| itemTransition | <DocsLink id="lng.Transition" /> | transition to apply to items on render      |

### Methods

#### appendItems(items: lng.Component[]): void

Adds items to the end of the child list

#### scrollTo(index: number, duration: number): void

scrolls to child at `index` at a rate of `duration` in ms \* (`this.selectedIndex` - `index`)

#### transitionDone(): void

This method is not set by default and can be overwritten. The method will be invoked upon
any transitions to the component's axis property finishing (ex. 'x' for Row, 'y' for Column).

#### shouldScrollDown(): bool

Returns a boolean for whether or not the component should scroll down, based off if the
component's `direction` property is `'column'`, the selected item's index is past the `scrollIndex`,
and that content that is out of view can be scrolled to.

#### shouldScrollLeft(): bool

Returns a boolean for whether or not the component should scroll left, based off if the
component's `direction` property is `'row'`, the selected item's index is past the `scrollIndex`,
and that content that is out of view can be scrolled to.

#### shouldScrollRight(): bool

Returns a boolean for whether or not the component should scroll right, based off if the
component's `direction` property is `'row'`, the selected item's index is past the `scrollIndex`,
and that content that is out of view can be scrolled to.

#### shouldScrollUp(): bool

Returns a boolean for whether or not the component should scroll up, based off if the
component's `direction` property is `'column'`, the selected item's index is past the `scrollIndex`,
and that content that is out of view can be scrolled to.

#### updatePositionOnAxis(item: lng.Component, position: number): void;

Updates the position of a component along the main axis of the NavigationManager component.
For components where `direction` is `'row'`, it will update the `x` property on the passed in component(`item`) to the passed in value(`position`).
For components where `direction` is `'column'`, it will update the `y` property on the passed in component(`item`) to the passed in value(`position`)
