import {
  Meta,
  Canvas,
  ArgsTable,
  Story,
  SourceState,
} from "@storybook/blocks";
import {
  ComponentHeading,
  EnumTable,
  Accessibility,
} from "../../storybook-components";
import { SingleSelect } from "./SingleSelect";
import { STATUS_VARIANT } from "../../types";

import {
  DemoSingleSelectSimple,
  DemoSingleSelectCategories,
  DemoSingleSelectForm,
  DemoSingleSelectNoResults,
  DemoSingleSelectNoResultsCustom,
  DemoSingleSelectLoading,
  DemoSingleSelectLoadingCustom,
  DemoSingleSelectAsyncExample,
  DemoSingleSelectPlaceholder,
  DemoSingleSelectPlaceholderElements,
  DemoSingleSelectClearable,
  DemoSingleSelectCreatable,
  DemoSingleSelectCategoriesCreatable,
  DemoSingleSelectVariants,
  DemoSingleSelectDisabledOption,
  DemoSingleSelectDisabled,
  DemoSelectInModal,
} from "./SingleSelectCSF.story";

<Meta title="Components/Forms/SingleSelect" component={SingleSelect} />

<ComponentHeading
  componentName="SingleSelect"
  description="Select component that utilizes downshift to select a single value"
  sourcePath="src/components/SelectNew/SingleSelect.tsx"
/>

## Installation

```jsx
import { SingleSelect } from "@conveyorhq/arrow-ds";
```

## Basic usage

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectSimple} />
</Canvas>

## API

### SingleSelect

<ArgsTable of={SingleSelect} />

### SingleSelect.Option

Extends `HTMLAttributes<HTMLDivElement>`. Passing `children` will replace the
default label.

<ArgsTable of={SingleSelect.Option} />

### SingleSelect.Category

This component also accepts `children`.

<ArgsTable of={SingleSelect.Category} />

### SingleSelect.Status

This component only accepts `children`.

## Enums

<EnumTable enums={{ STATUS_VARIANT }} />

<Accessibility
  keyboardInteractions={[
    {
      key: "Escape",
      description: "Closes the menu, if open",
    },
    {
      key: "Up Arrow / Down Arrow",
      description: "Changes highlighted item when menu is open",
    },
    {
      key: "Tab / Shift + Tab",
      description: "Changes highlighted item when menu is open",
    },
    {
      key: "Space / Enter",
      description:
        "If the component is focused and closed, either of these keys will open it. Pressing either of these when the menu is open will select the currently highlighted item or close the menu if none is highlighted.",
    },
  ]}
/>

## Demos

### Option Categories

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectCategories} />
</Canvas>

### FormGroup

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectForm} />
</Canvas>

### No Matches Found

When an `inputValue` is provided but `children` is just an empty array, a
default “No matches found” message is shown.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectNoResults} />
</Canvas>

You can override the default “No matches found” message with a custom one passed
to `children`.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectNoResultsCustom} />
</Canvas>

### Loading

When `isLoading` is set to `true`, a loading indicator will be visible. If
`children` is an empty array, a default “Loading…” message will appear in the
dropdown.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectLoading} />
</Canvas>

When `isLoading` is `true`, you can override the default “Loading…” message with
a custom one passed to `children`.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectLoadingCustom} />
</Canvas>

Here is a full example of an `SingleSelect` that fetches results from a server.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectAsyncExample} />
</Canvas>

### Placeholder

If a `placeholder` is provided, it will show when there is a `null` value
provided to `selected`.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectPlaceholder} />
</Canvas>

The `placeholder` prop will also accept more than a string.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectPlaceholderElements} />
</Canvas>

### Clearable

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectClearable} />
</Canvas>

### Creatable

When a function is provided to the `onCreateOption` prop, it adds a “Create…”
option to the top of the list when searching. This will only be visible when the
`inputValue` is not an empty string.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectCreatable} />
</Canvas>

This next demo is a semi-ridiculous use case and is just meant to demonstrate
the flexibility of the component.

To create an option in the "Nuts" category, include “nuts” somewhere in your
query before creating.

To create an option where `hasDairy` is set to `true`, include the word “dairy”
somewhere in your query before creating.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectCategoriesCreatable} />
</Canvas>

### Variants

If inside a `FormGroup`, `SingleSelect` will use the value provided via context.
To override, provide a `STATUS_VARIANT` directly to the `variant` prop.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectVariants} />
</Canvas>

### Disabled

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectDisabled} />
</Canvas>

### Disabled Options

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSingleSelectDisabledOption} />
</Canvas>

### In a modal

The select menu displaying correctly inside of a modal.

<Canvas withSource={SourceState.OPEN}>
  <Story story={DemoSelectInModal} />
</Canvas>
