import { Layout, Playground, Attributes } from 'lib/components'
import { AutoComplete, Spacer, Badge, Grid, Text } from 'components'
import { useState, useRef, useEffect } from 'react'

export const meta = {
  title: 'Auto-Complete',
  group: 'Data Entry',
}

## Auto Complete

AutoComplete control of input field.

<Playground
  desc="Basic usage, add auto-complete list for all inputs."
  scope={{ AutoComplete }}
  code={`
() => {
  const options = [
    { label: 'London', value: 'london' },
    { label: 'Sydney', value: 'sydney' },
    { label: 'Shanghai', value: 'shanghai' },
  ]
  return <AutoComplete placeholder="Enter here" options={options} />
}
`}
/>

<Playground
  desc="Disable all."
  title="disabled"
  scope={{ AutoComplete }}
  code={`
() => {
  const options = [
    { label: 'London', value: 'london' },
    { label: 'Sydney', value: 'sydney' },
    { label: 'Shanghai', value: 'shanghai' },
  ]
  return <AutoComplete disabled options={options} initialValue="London" />
}
`}
/>

<Playground
  title="Only allow selected"
  desc="You can only change the value of the input by select."
  scope={{ AutoComplete }}
  code={`
() => {
  const options = [
    { label: 'London', value: 'london' },
    { label: 'Sydney', value: 'sydney' },
    { label: 'Shanghai', value: 'shanghai' },
  ]
  return <AutoComplete disableFreeSolo options={options} initialValue="sydney" />
}
`}
/>

<Playground
  desc="Update the contents of drop-down list based on input."
  title="search"
  scope={{ AutoComplete }}
  code={`
() => {
  const allOptions = [
    { label: 'London', value: 'london' },
    { label: 'Sydney', value: 'sydney' },
    { label: 'Shanghai', value: 'shanghai' },
  ]
  const [options, setOptions] = React.useState()
  const searchHandler = (currentValue) => {
    if (!currentValue) return setOptions([])
    const relatedOptions = allOptions.filter(item => item.value.includes(currentValue))
    setOptions(relatedOptions)
  }
  return <AutoComplete options={options} placeholder="Enter here" onSearch={searchHandler} />
}
`}
/>

<Playground
  title="Waiting in search"
  desc="Show friendly tips and UI when searching."
  scope={{ AutoComplete, useState, useEffect, useRef }}
  code={`
() => {
  const allOptions = [
    { label: 'London', value: 'london' },
    { label: 'Sydney', value: 'sydney' },
    { label: 'Shanghai', value: 'shanghai' },
  ]
  const [options, setOptions] = useState()
  const [searching, setSearching] = useState(false)
  const timer = useRef()
  // triggered every time input
  const searchHandler = (currentValue) => {
    if (!currentValue) return setOptions([])
    setSearching(true)
    const relatedOptions = allOptions.filter(item => item.value.includes(currentValue))
    // this is mock async request
    // you can get data in any way
    timer.current && clearTimeout(timer.current)
    timer.current = setTimeout(() => {
      setOptions(relatedOptions)
      setSearching(false)
      clearTimeout(timer.current)
    }, 1000)
  }
  return (
    <AutoComplete searching={searching}
      options={options}
      placeholder="Enter here"
      onSearch={searchHandler} />
  )
}
`}
/>

<Playground
  title="custom searching text"
  desc="You can replace the default waiting text with any components."
  scope={{ AutoComplete }}
  code={`
<AutoComplete searching placeholder="Enter here" width="100%">
  <AutoComplete.Searching>
    <span style={{ color: 'red' }}>waiting...</span>
  </AutoComplete.Searching>
</AutoComplete>
`}
/>

<Playground
  title="custom no options"
  desc="You can also customize the prompt with no options."
  scope={{ AutoComplete, useState }}
  code={`
() => {
  const allOptions = [
    { label: 'London', value: 'london' },
    { label: 'Sydney', value: 'sydney' },
    { label: 'Shanghai', value: 'shanghai' },
  ]
  const [options, setOptions] = useState()
  const searchHandler = (currentValue) => {
    if (!currentValue) return setOptions([])
    const relatedOptions = allOptions.filter(item => item.value.includes(currentValue))
    setOptions(relatedOptions)
  }
  return (
    <AutoComplete placeholder="Enter here" width="100%" options={options} onSearch={searchHandler}>
      <AutoComplete.Empty>
        <span>no options...</span>
      </AutoComplete.Empty>
    </AutoComplete>
  )
}
`}
/>

<Playground
  title="custom option"
  desc="You can rewrite each item of the `AutoComplete` to express more."
  scope={{ AutoComplete, useState, Text, Badge, Grid }}
  code={`
() => {
  const makeOption = (label, value) => (
    <AutoComplete.Option value={value}>
      <Grid.Container style={{ padding: '10pt 0' }}>
        <Grid xs={24}><Text span b size="1.2rem">Recent search results </Text></Grid>
        <Grid.Container xs={24}>
          <Grid xs><Text span>{label}</Text></Grid>
          <Grid xs={4}><Badge type="success">Recommended</Badge></Grid>
        </Grid.Container>
      </Grid.Container>
    </AutoComplete.Option>
  )
  const allOptions = [
    { label: 'London', value: 'london' },
    { label: 'Sydney', value: 'sydney' },
    { label: 'Shanghai', value: 'shanghai' },
  ]
  const [options, setOptions] = useState()
  const searchHandler = (currentValue) => {
    if (!currentValue) return setOptions([])
    const relatedOptions = allOptions.filter(item => item.value.includes(currentValue))
    const customOptions = relatedOptions.map(({ label, value }) => makeOption(label, value))
    setOptions(customOptions)
  }
  return (
    <AutoComplete placeholder="Enter here"
      width="100%"
      options={options}
      onSearch={searchHandler} />
  )
}
`}
/>

<Playground
  title="sizes"
  desc="Components of different sizes."
  scope={{ AutoComplete, Spacer }}
  code={`
() => {
  const options = [
    { label: 'London', value: 'london' },
    { label: 'Sydney', value: 'sydney' },
    { label: 'Shanghai', value: 'shanghai' },
  ]
  return (
    <>
      <AutoComplete placeholder="Mini" size="mini" options={options} />
      <Spacer y={.5} />
      <AutoComplete placeholder="Small" size="small" options={options} />
      <Spacer y={.5} />
      <AutoComplete placeholder="Medium" size="medium" options={options} />
      <Spacer y={.5} />
      <AutoComplete placeholder="Large" size="large" options={options} />
    </>
  )
}
`}
/>

<Playground
  title="clearable"
  desc="Add a clear button in the input box."
  scope={{ AutoComplete }}
  code={`
() => {
  const options = [
    { label: 'London', value: 'london' },
    { label: 'Sydney', value: 'sydney' },
    { label: 'Shanghai', value: 'shanghai' },
  ]
  return <AutoComplete placeholder="Enter here" clearable options={options} />
}
`}
/>

<Playground
  title="Creatable"
  desc="Add an entry to be selected for any value."
  scope={{ AutoComplete }}
  code={`
() => {
  const allOptions = [
    { label: 'London', value: 'london' },
    { label: 'Sydney', value: 'sydney' },
    { label: 'Shanghai', value: 'shanghai' },
  ]
  const [options, setOptions] = React.useState()
  const searchHandler = (currentValue) => {
    const createOptions = [{
      value: currentValue, label: 'Add "' + currentValue + '"'
    }]
    if (!currentValue) return setOptions([])
    const relatedOptions = allOptions.filter(item => item.value.includes(currentValue))
    const optionsWithCreatable = relatedOptions.length !== 0 ? relatedOptions : createOptions
    setOptions(optionsWithCreatable)
  }
  return <AutoComplete options={options} clearable disableFreeSolo placeholder="Enter here" onSearch={searchHandler} />
}
`}
/>

<Attributes edit="/pages/en-us/components/auto-complete.mdx">
<Attributes.Title>AutoComplete.Props</Attributes.Title>

| Attribute             | Description                               | Type                                             | Accepted values                                         | Default   |
| --------------------- | ----------------------------------------- | ------------------------------------------------ | ------------------------------------------------------- | --------- |
| **options**           | options of input                          | [AutoCompleteOptions](#type-autocompleteoptions) | -                                                       | -         |
| **status**            | input type                                | `NormalTypes`                                    | `'default', 'secondary', 'success', 'warning', 'error'` | `default` |
| **size**              | input size                                | `NormalSizes`                                    | `'mini', 'small', 'medium', 'large'`                    | `medium`  |
| **initialValue**      | initial value                             | `string`                                         | -                                                       | -         |
| **value**             | current value                             | `string`                                         | -                                                       | -         |
| **width**             | container width                           | `string`                                         | -                                                       | -         |
| **clearable**         | show clear icon                           | `boolean`                                        | -                                                       | `false`   |
| **searching**         | show loading icon for search              | `boolean`                                        | -                                                       | `false`   |
| **onChange**          | value of input is changed                 | `(value: string) => void`                        | -                                                       | -         |
| **onSearch**          | called when searching items               | `(value: string) => void`                        | -                                                       | -         |
| **onSelect**          | called when a option is selected          | `(value: string) => void`                        | -                                                       | -         |
| **dropdownClassName** | className of dropdown box                 | `string`                                         | -                                                       | -         |
| **dropdownStyle**     | style of dropdown box                     | `object`                                         | -                                                       | -         |
| **disableMatchWidth** | disable Option from follow parent width   | `boolean`                                        | -                                                       | `false`   |
| **disableFreeSolo**   | only values can be changed through Select | `boolean`                                        | -                                                       | `false`   |
| ...                   | native props                              | `InputHTMLAttributes`                            | `'id', 'className', ...`                                | -         |

<Attributes.Title alias="AutoComplete.Option">AutoComplete.Item</Attributes.Title>

| Attribute | Description          | Type             | Accepted values          | Default |
| --------- | -------------------- | ---------------- | ------------------------ | ------- |
| **value** | a unique ident value | `string`         | -                        | -       |
| ...       | native props         | `HTMLAttributes` | `'id', 'className', ...` | -       |

<Attributes.Title>AutoComplete.Searching</Attributes.Title>

| Attribute | Description  | Type             | Accepted values          | Default |
| --------- | ------------ | ---------------- | ------------------------ | ------- |
| ...       | native props | `HTMLAttributes` | `'id', 'className', ...` | -       |

<Attributes.Title>AutoComplete.Empty</Attributes.Title>

| Attribute | Description    | Type             | Accepted values          | Default |
| --------- | -------------- | ---------------- | ------------------------ | ------- |
| hidden    | hide empty box | `boolean`        | -                        | `false` |
| ...       | native props   | `HTMLAttributes` | `'id', 'className', ...` | -       |

<Attributes.Title>type AutoCompleteOptions</Attributes.Title>

```ts
Array<{
  label: string
  value: string
} | AutoComplete.Item>
```

</Attributes>

export default ({ children }) => <Layout meta={meta}>{children}</Layout>
