{/* 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 ColumnStories from './Column.stories';

<Meta of={ColumnStories} />

<Title />

Focus management and smooth scrolling for a list of vertically-oriented items.

## Source

https://github.com/rdkcentral/Lightning-UI-Components/blob/develop/packages/%40lightningjs/ui-components/src/components/Column/Column.js

## Usage

`Column` expects a list of `items` which will be laid out top-to-bottom. By default, the width of `Column`'s Item container is the same as the width of the widest item, and the height is the height passed in, the height of the wrapping FocusManager if available, or the height of the stage by default. You can change the `w` and `h` attributes to manage `width` and `height`, respectively.

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

class BasicExample extends lng.Component {
  static _template() {
    return {
      Column: {
        type: Column,
        items: [
          // list of items
        ]
      }
    };
  }

  _getFocused() {
    return this.tag('Column');
  }
}
```

The `Column` component extends [FocusManager](?path=/docs/components-focusmanager--docs), so you need to make sure that `_getFocused` returns the `Column` component.

### Column items with changing height

If the heights of various items in the column can change (ex. an item which expands), the layout
of the items in the Column must be recalculated. To trigger this update, fire an event, called `$itemChanged`, from the
item when its height changes.
ex.

```js
class ExpandingButton extends Button {
  _focus() {
    super._focus();
    this.patch({ h: 100 });
    // triggers recalculation of Column items layout
    this.fireAncestors('$itemChanged');
  }

  _unfocus() {
    super._unfocus();
    this.patch({ h: 40 });
  }
}

class ExpandableHeightItems extends lng.Component {
  static _template() {
    return {
      Column: {
        type: Column,
        h: 500,
        items: Array.apply(null, { length: 15 }).map((_, i) => ({
          type: ExpandingButton,
          h: 40,
          w: 150,
          buttonText: `Button ${i}`
        }))
      }
    };
  }

  _getFocused() {
    return this.tag('Column');
  }
}
```

### Scrolling

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`.

## API

### Properties

| name          | type                                                    | required | default   | description                                                                                                                                  |
| ------------- | ------------------------------------------------------- | -------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| items         | <DocsLink id="lng.Component">lng.Component[]</DocsLink> | false    | undefined | components to be listed in the column.                                                                                                       |
| onScreenItems | array                                                   | true     | undefined | list of items that are currently on screen within the bounds of the container.                                                               |
| plinko        | boolean                                                 | false    | false     | when `true`, the component will determine the nearest horizontal index of the next focused item's children. if `Column` has `Row`s as items. |
| selected      | <DocsLink id="lng.Component" />                         | true     | undefined | component that is currently in focus                                                                                                         |
| selectedIndex | number                                                  | false    | 0         | index of currently selected item                                                                                                             |

### Style Properties

The Column component shares the same style properties as the ones listed in NavigationManager. For a detailed description, please refer to style properties section in the [NavigationManager component](?path=/docs/components-navigationmanager--docs#style-properties)

### Child Item Properties

The `Column` component will utilize the following properties on each individual element in its `items` array:

| name             | type    | required | default | description                                                                                             |
| ---------------- | ------- | -------- | ------- | ------------------------------------------------------------------------------------------------------- |
| centerInParent   | boolean | false    | false   | when true, it places the child component in center of the parent                                        |
| extraItemSpacing | number  | false    | 0       | additional space to be added between items                                                              |
| skipPlinko       | boolean | false    | false   | when true, plinko will use the previous item to determine the horizontal index of the next focused item |

### Methods

The Column component is a subclass of NavigationManager and FocusManager, so inherits all methods from those parent components. These shared methods are already documented in the NavigationManager and FocusManager documentation. For detailed descriptions of these methods, please refer to the methods section in the [NavigationManager](?path=/docs/components-navigationmanager--docs) and [FocusManager](?path=/docs/components-focusmanager--docs) documentation.

#### onScreenEffect(): void

A callback that can be overridden to do something with the items that are currently on screen. This will be called on every new render.

### Events

#### $columnEmpty(): void

Fires when all of the items have been removed from a `Column`
