Skip to content

Commit

Permalink
[5.2.0-rc.2]feat: Slider support popover
Browse files Browse the repository at this point in the history
  • Loading branch information
1uokun committed Jul 16, 2024
1 parent c9dcb5c commit 4af9be0
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 10 deletions.
5 changes: 2 additions & 3 deletions components/slider/PropsType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ export type SliderProps = {
disabled?: boolean
range?: boolean
icon?: ReactNode
// TODO-luokun
// popover?: boolean | ((value: number) => ReactNode)
// residentPopover?: boolean
popover?: boolean | ((value: number) => ReactNode)
residentPopover?: boolean
onChange?: (value: SliderValue) => void
onAfterChange?: (value: SliderValue) => void
style?: StyleProp<ViewStyle>
Expand Down
5 changes: 5 additions & 0 deletions components/slider/demo/basic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ export default function StepperExample() {
<Slider marks={marks} ticks range defaultValue={[60, 40]} />
</List.Item>
</List>
<List renderHeader={'在拖动时显示悬浮提示'}>
<List.Item>
<Slider popover />
</List.Item>
</List>
</ScrollView>
)
}
2 changes: 2 additions & 0 deletions components/slider/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ A Slider component for selecting particular value in range, eg: controls the dis
| min | Min value | `number` | `0` | |
| onAfterChange | Consistent with the trigger timing of `touchend`, pass the current value as a parameter | `(value: number | [number, number]) => void` | - | |
| onChange | Triggered when the slider is dragged, and the current dragged value is passed in as a parameter | `(value: number | [number, number]) => void` | - | |
| popover | Whether to display the popover when dragging. Support passing in function to customize the rendering content. | `boolean | ((value: number) => ReactNode)` | `false` | `5.2.0` |
| residentPopover | Whether the `popover` is permanently displayed , this attribute takes effect when `popover` exists | `boolean ` | `false` | `5.2.0` |
| range | Whether it is a double sliders | `boolean` | `false` | `5.2.0` |
| step | Step distance, the value must be greater than `0`, and `(max-min)` can be divisible by `step`. When `marks` is not null, the configuration of `step` is invalid | `number` | `1` | `5.2.0` |
| ticks | Whether to display the scale | `boolean` | `false` | `5.2.0` |
Expand Down
2 changes: 2 additions & 0 deletions components/slider/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ version: 5.2.0-rc.1
| min | 最小值 | `number` | `0` | |
| onAfterChange |`touchend` 触发时机一致,把当前值作为参数传入 | `(value: number | [number, number]) => void` | - | |
| onChange | 拖拽滑块时触发,并把当前拖拽的值作为参数传入 | `(value: number | [number, number]) => void` | - | |
| popover | 是否在拖动时显示悬浮提示,支持传入函数自定义渲染内容 | `boolean | ((value: number) => ReactNode)` | `false` | `5.2.0` |
| residentPopover | `popover` 是否常驻显示,`popover` 存在时生效 | `boolean ` | `false` | `5.2.0` |
| range | 是否为双滑块 | `boolean` | `false` | `5.2.0` |
| step | 步距,取值必须大于 `0`,并且 `(max - min)` 可被 `step` 整除。当 `marks` 不为空对象时,`step` 的配置失效 | `number` | `1` | `5.2.0` |
| ticks | 是否显示刻度 | `boolean` | `false` | `5.2.0` |
Expand Down
4 changes: 2 additions & 2 deletions components/slider/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ export const Slider: React.FC<SliderProps> = (props) => {
max={max}
disabled={disabled}
icon={icon}
// popover={!!props.popover}
// residentPopover={!!props.residentPopover}
popover={!!props.popover}
residentPopover={!!props.residentPopover}
onDrag={(locationX, last) => {
if (!trackLayout) {
return
Expand Down
37 changes: 32 additions & 5 deletions components/slider/thumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import {
LayoutChangeEvent,
LayoutRectangle,
StyleProp,
View,
ViewStyle,
} from 'react-native'
import { Gesture, GestureDetector } from 'react-native-gesture-handler'
import Animated, { runOnJS, useAnimatedStyle } from 'react-native-reanimated'
import Tooltip from '../tooltip'
import { SliderStyle } from './style'
import { ThumbIcon } from './thumb-icon'

Expand All @@ -19,8 +21,8 @@ type ThumbProps = {
trackLayout?: LayoutRectangle
onDrag: (value: number, last?: boolean) => void
icon?: ReactNode
// popover: boolean | ((value: number) => ReactNode)
// residentPopover: boolean
popover: boolean | ((value: number) => ReactNode)
residentPopover: boolean
style?: StyleProp<ViewStyle>
styles: Partial<SliderStyle>
}
Expand All @@ -33,6 +35,7 @@ const Thumb: FC<ThumbProps> = (props) => {
trackLayout,
disabled,
icon,
residentPopover,
onDrag,
style,
styles,
Expand All @@ -53,24 +56,48 @@ const Thumb: FC<ThumbProps> = (props) => {
setThumbLayout(e.nativeEvent.layout)
}

const [dragging, setDragging] = useState(false)

const gesture = Gesture.Pan()
.enabled(!disabled)
.onBegin(() => {})
.onUpdate((e) => {
!dragging && runOnJS(setDragging)(true)
runOnJS(onDrag)(e.absoluteX - (thumbLayout?.width || 0))
})
.onEnd((e) => {
runOnJS(onDrag)(e.absoluteX - (thumbLayout?.width || 0), true)
})
.onFinalize(() => {})
.onFinalize(() => {
runOnJS(setDragging)(false)
})

const renderPopoverContent =
typeof props.popover === 'function'
? props.popover
: props.popover
? (val: number) => val.toString()
: null

const thumbElement = icon ? icon : <ThumbIcon />

return (
<GestureDetector gesture={gesture}>
<Animated.View
onStartShouldSetResponder={() => true}
style={[styles.thumb, animatedStyles, style]}
onLayout={handleLayout}>
{icon ? icon : <ThumbIcon />}
{renderPopoverContent ? (
<Tooltip
content={renderPopoverContent(value)}
placement="top"
visible={residentPopover || dragging}
getContainer={null}
mode="dark">
<View style={{ flex: 1 }}>{thumbElement}</View>
</Tooltip>
) : (
thumbElement
)}
</Animated.View>
</GestureDetector>
)
Expand Down

0 comments on commit 4af9be0

Please sign in to comment.