<commit_before>import React from 'react'
import {capitalize} from 'lodash'
import {useId} from '@reach/auto-id'
import {isTitledListValue, TitledListValue} from '@sanity/types'
import {Inline, Stack, Card, Text, Select, Flex, Radio, Box} from '@sanity/ui'
import {FormField} from '@sanity/base/components'
import PatchEvent, {set, unset} from '../PatchEvent'
import {Props} from './types'

function toSelectItem(
  option: TitledListValue<string | number> | string | number
): TitledListValue<string | number> {
  return isTitledListValue(option) ? option : {title: capitalize(`${option}`), value: option}
}

const EMPTY_ITEM = {title: '', value: undefined}

const SelectInput = React.forwardRef(function SelectInput(
  props: Props<string | number>,
  forwardedRef: React.ForwardedRef<HTMLSelectElement | HTMLInputElement>
) {
  const {value, readOnly, markers, type, level, onChange, presence} = props
  const items = ((type.options?.list || []) as unknown[]).map(toSelectItem)
  const currentItem = items.find((item) => item.value === value)
  const isRadio = type.options && type.options.layout === 'radio'
  const validation = markers.filter((marker) => marker.type === 'validation')
  const errors = validation.filter((marker) => marker.level === 'error')

  const itemFromOptionValue = (optionValue) => {
    const index = Number(optionValue)

    return items[index]
  }

  const optionValueFromItem = (item) => {
    return String(items.indexOf(item))
  }

  const inputId = useId()
  const handleChange = React.useCallback(
    (nextItem: TitledListValue<string | number>) => {
      onChange(
        PatchEvent.from(typeof nextItem.value === 'undefined' ? unset() : set(nextItem.value))
      )
    },
    [onChange]
  )

  const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
    const nextItem = itemFromOptionValue(event.currentTarget.value)

    if (!nextItem) {
      handleChange(EMPTY_ITEM)
      return
    }

    handleChange(nextItem)
  }

  return (
    <FormField
      inputId={inputId}
      level={level}
      title={type.title}
      description={type.description}
      __unstable_markers={markers}
      __unstable_presence={presence}
    >
      {isRadio ? (
        <RadioSelect
          items={items}
          value={currentItem}
          onChange={handleChange}
          direction={type.options.direction || 'vertical'}
          ref={forwardedRef as React.ForwardedRef<HTMLInputElement>}
          readOnly={readOnly}
          customValidity={errors?.[0]?.item.message}
        />
      ) : (
        <Select
          onChange={handleSelectChange}
          id={inputId}
          ref={forwardedRef as React.ForwardedRef<HTMLSelectElement>}
          readOnly={readOnly}
          customValidity={errors?.[0]?.item.message}
          value={optionValueFromItem(currentItem)}
        >
          {[EMPTY_ITEM, ...items].map((item, i) => (
            <option key={`${i - 1}`} value={i - 1}>
              {item.title}
            </option>
          ))}
        </Select>
      )}
    </FormField>
  )
})

export default SelectInput

const RadioSelect = React.forwardRef(function RadioSelect(
  props: {
    items: TitledListValue<string | number>[]
    value: TitledListValue<string | number>
    direction: 'horizontal' | 'vertical'
    readOnly: boolean
    onChange: (value: TitledListValue<string | number> | null) => void
    customValidity?: string
  },
  forwardedRef: React.ForwardedRef<HTMLInputElement>
) {
  const {items, value, onChange, readOnly, customValidity, direction} = props

  const Layout = direction === 'horizontal' ? Inline : Stack
  return (
    <Card border padding={4} radius={1}>
      <Layout space={4} role="group">
        {items.map((item, index) => (
          <Flex key={index} as="label" align="center">
            <Radio
              ref={index === 0 ? forwardedRef : null}
              checked={value === item}
              onChange={() => onChange(item)}
              readOnly={readOnly}
              customValidity={customValidity}
            />
            <Box marginLeft={3}><commit_msg>[form-builder] Add inputId as name to RadioSelect<commit_after>import React from 'react'
import {capitalize} from 'lodash'
import {useId} from '@reach/auto-id'
import {isTitledListValue, TitledListValue} from '@sanity/types'
import {Inline, Stack, Card, Text, Select, Flex, Radio, Box} from '@sanity/ui'
import {FormField} from '@sanity/base/components'
import PatchEvent, {set, unset} from '../PatchEvent'
import {Props} from './types'

function toSelectItem(
  option: TitledListValue<string | number> | string | number
): TitledListValue<string | number> {
  return isTitledListValue(option) ? option : {title: capitalize(`${option}`), value: option}
}

const EMPTY_ITEM = {title: '', value: undefined}

const SelectInput = React.forwardRef(function SelectInput(
  props: Props<string | number>,
  forwardedRef: React.ForwardedRef<HTMLSelectElement | HTMLInputElement>
) {
  const {value, readOnly, markers, type, level, onChange, presence} = props
  const items = ((type.options?.list || []) as unknown[]).map(toSelectItem)
  const currentItem = items.find((item) => item.value === value)
  const isRadio = type.options && type.options.layout === 'radio'
  const validation = markers.filter((marker) => marker.type === 'validation')
  const errors = validation.filter((marker) => marker.level === 'error')

  const itemFromOptionValue = (optionValue) => {
    const index = Number(optionValue)

    return items[index]
  }

  const optionValueFromItem = (item) => {
    return String(items.indexOf(item))
  }

  const inputId = useId()
  const handleChange = React.useCallback(
    (nextItem: TitledListValue<string | number>) => {
      onChange(
        PatchEvent.from(typeof nextItem.value === 'undefined' ? unset() : set(nextItem.value))
      )
    },
    [onChange]
  )

  const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
    const nextItem = itemFromOptionValue(event.currentTarget.value)

    if (!nextItem) {
      handleChange(EMPTY_ITEM)
      return
    }

    handleChange(nextItem)
  }

  return (
    <FormField
      inputId={inputId}
      level={level}
      title={type.title}
      description={type.description}
      __unstable_markers={markers}
      __unstable_presence={presence}
    >
      {isRadio ? (
        <RadioSelect
          inputId={inputId}
          items={items}
          value={currentItem}
          onChange={handleChange}
          direction={type.options.direction || 'vertical'}
          ref={forwardedRef as React.ForwardedRef<HTMLInputElement>}
          readOnly={readOnly}
          customValidity={errors?.[0]?.item.message}
        />
      ) : (
        <Select
          onChange={handleSelectChange}
          id={inputId}
          ref={forwardedRef as React.ForwardedRef<HTMLSelectElement>}
          readOnly={readOnly}
          customValidity={errors?.[0]?.item.message}
          value={optionValueFromItem(currentItem)}
        >
          {[EMPTY_ITEM, ...items].map((item, i) => (
            <option key={`${i - 1}`} value={i - 1}>
              {item.title}
            </option>
          ))}
        </Select>
      )}
    </FormField>
  )
})

export default SelectInput

const RadioSelect = React.forwardRef(function RadioSelect(
  props: {
    items: TitledListValue<string | number>[]
    value: TitledListValue<string | number>
    direction: 'horizontal' | 'vertical'
    readOnly: boolean
    onChange: (value: TitledListValue<string | number> | null) => void
    customValidity?: string
    inputId?: string
  },
  forwardedRef: React.ForwardedRef<HTMLInputElement>
) {
  const {items, value, onChange, readOnly, customValidity, direction, inputId} = props

  const Layout = direction === 'horizontal' ? Inline : Stack
  return (
    <Card border padding={4} radius={1}>
      <Layout space={4} role="group">
        {items.map((item, index) => (
          <Flex key={index} as="label" align="center">
            <Radio
              ref={index === 0 ? forwardedRef : null}
              checked={value === item}
              onChange={() => onChange(item)}
              readOnly={readOnly}
              customValidity={customValidity}
              name={inputId}
            />
            <Box marginLeft={3}>
{'fraction_non_alphanumeric': 0.1358780458528388, 'fraction_numerical': 0.0021606049693914295, 'mean_word_length': 3.034866828087167, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3831050', 'n_tokens_mistral': 2451, 'n_tokens_neox': 2431, 'n_words': 528}