import React from 'react'
import { Slider as RNSlider } from '@miblanchard/react-native-slider'
import { TypeGuards } from '@codeleap/types'
import { onUpdate } from '@codeleap/hooks'
import { SliderProps, TrackMarkProps } from './types'
import { InputBase, selectInputBaseProps } from '../InputBase'
import { Text } from '../Text'
import { View } from '../View'
import { Touchable } from '../Touchable'
import { AnyRecord, IJSX, StyledComponentProps } from '@codeleap/styles'
import { MobileStyleRegistry } from '../../Registry'
import { useStylesFor } from '../../hooks'
import { useInputBase } from '../InputBase/useInputBase'
import { fields } from '@codeleap/form'
import { useInputBasePartialStyles } from '../InputBase/useInputBasePartialStyles'
export * from './styles'
export * from './types'
const DefaultSliderTrackMark = (props: TrackMarkProps) => {
const { style, onPress } = props
if (!TypeGuards.isString(props.content)) {
return <>
{props.content}
>
}
return
}
const minimumValue = 0
const maximumValue = 100
export const Slider = (props: SliderProps) => {
const {
inputBaseProps: { label: _label, description: _description, ..._inputBaseProps },
others,
} = selectInputBaseProps({
...Slider.defaultProps,
...props,
})
const {
debounce = null,
field,
label,
description,
debugName,
style,
disabled,
trackMarks,
trackMarksClickable,
labelClickable,
updateImmediately = false,
trackMarkComponent: SliderTrackMark,
value,
onValueChange,
...sliderProps
} = others
const {
wrapperRef,
inputValue,
onInputValueChange,
} = useInputBase(field, fields.number, { value, onValueChange })
/**
* When `updateImmediately` is false, the committed value is only written on `onSlidingComplete`
* to avoid flooding the form/state store with every pixel of movement; `_value` is the local
* thumb position and `inputValue` is the last committed value.
*/
const [_value, _setValue] = updateImmediately ? [inputValue, onInputValueChange] : React.useState>(0)
onUpdate(() => {
if (updateImmediately) return
if (inputValue !== _value) {
_setValue(inputValue)
}
}, [inputValue])
const styles = useStylesFor(Slider.styleRegistryName, style)
const partialStyles = useInputBasePartialStyles(
styles,
['thumb', 'track', 'selectedTrack', 'unselectedTrack', 'sliderContainer', 'trackMark'],
{ disabled }
)
const trackMarksHaveContent = !(TypeGuards.isArray(trackMarks) || TypeGuards.isNil(trackMarks))
const trackMarksProp = React.useMemo(() => {
if (!trackMarksHaveContent) {
return trackMarks
}
return Object.keys(trackMarks).map((key) => Number(key))
}, [trackMarksHaveContent])
return (
{label || description ? (
{label ? (
labelClickable ? onInputValueChange(sliderProps?.minimumValue || minimumValue) : null}
style={styles.labelBtn}
debugName='slider title'
>
) : null}
{description ? (
labelClickable ? onInputValueChange(sliderProps?.maximumValue || maximumValue) : null}
style={styles?.descriptionBtn}
debugName='slider description'
>
) : null}
) : null}
{/* @ts-ignore */}
{
if (updateImmediately) return
onInputValueChange(_value)
}}
disabled={disabled}
{...sliderProps}
trackMarks={trackMarksProp}
/>
{
trackMarksProp ? (
{
trackMarksProp.map((_, idx) => {
let idxStyle = {}
if (idx === 0) {
idxStyle = styles?.firstTrackMark
} else if (idx === trackMarksProp.length - 1) {
idxStyle = styles?.lastTrackMark
}
const style = [partialStyles?.trackMark, idxStyle]
if (!trackMarksHaveContent) {
return trackMarksClickable ? onInputValueChange(trackMarksProp[idx]) : null}
/>
}
const relativeValue = trackMarksProp[idx]
const content = trackMarks[relativeValue]
return trackMarksClickable ? onInputValueChange(trackMarksProp[idx]) : null}
/>
})
}
) : null
}
)
}
Slider.styleRegistryName = 'Slider'
Slider.rootElement = 'wrapper'
Slider.elements = [
...InputBase.elements,
'thumb',
'track',
'selectedTrack',
'unselectedTrack',
'firstTrackMark',
'lastTrackMark',
'sliderContainer',
'labelBtn',
'descriptionBtn',
]
Slider.withVariantTypes = (styles: S) => {
return Slider as (props: StyledComponentProps) => IJSX
}
Slider.defaultProps = {
trackMarksClickable: false,
labelClickable: false,
trackMarkComponent: DefaultSliderTrackMark,
} as Partial
MobileStyleRegistry.registerComponent(Slider)