@tamagui/slider 1.0.1-beta.56 → 1.0.1-beta.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Slider.js +4 -3
- package/dist/cjs/Slider.js.map +2 -2
- package/dist/cjs/SliderImpl.js +1 -1
- package/dist/cjs/SliderImpl.js.map +2 -2
- package/dist/esm/Slider.js +4 -3
- package/dist/esm/Slider.js.map +2 -2
- package/dist/esm/SliderImpl.js +1 -1
- package/dist/esm/SliderImpl.js.map +2 -2
- package/dist/jsx/Slider.js +5 -3
- package/dist/jsx/SliderImpl.js +1 -1
- package/package.json +9 -8
- package/src/Slider.tsx +584 -0
- package/src/SliderImpl.tsx +105 -0
- package/src/constants.tsx +32 -0
- package/src/helpers.tsx +102 -0
- package/src/index.ts +7 -0
- package/src/types.ts +78 -0
- package/types/Slider.d.ts.map +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { SizeTokens } from '@tamagui/core'
|
|
2
|
+
import { createContextScope } from '@tamagui/create-context'
|
|
3
|
+
|
|
4
|
+
import { Direction, SliderContextValue } from './types'
|
|
5
|
+
|
|
6
|
+
export const SLIDER_NAME = 'Slider'
|
|
7
|
+
|
|
8
|
+
export const [createSliderContext, createSliderScope] = createContextScope(SLIDER_NAME)
|
|
9
|
+
|
|
10
|
+
export const [SliderProvider, useSliderContext] =
|
|
11
|
+
createSliderContext<SliderContextValue>(SLIDER_NAME)
|
|
12
|
+
|
|
13
|
+
export const [SliderOrientationProvider, useSliderOrientationContext] = createSliderContext<{
|
|
14
|
+
startEdge: 'bottom' | 'left' | 'right'
|
|
15
|
+
endEdge: 'top' | 'right' | 'left'
|
|
16
|
+
sizeProp: 'width' | 'height'
|
|
17
|
+
size: number | SizeTokens
|
|
18
|
+
direction: number
|
|
19
|
+
}>(SLIDER_NAME, {
|
|
20
|
+
startEdge: 'left',
|
|
21
|
+
endEdge: 'right',
|
|
22
|
+
sizeProp: 'width',
|
|
23
|
+
size: 0,
|
|
24
|
+
direction: 1,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
export const PAGE_KEYS = ['PageUp', 'PageDown']
|
|
28
|
+
export const ARROW_KEYS = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']
|
|
29
|
+
export const BACK_KEYS: Record<Direction, string[]> = {
|
|
30
|
+
ltr: ['ArrowDown', 'Home', 'ArrowLeft', 'PageDown'],
|
|
31
|
+
rtl: ['ArrowDown', 'Home', 'ArrowRight', 'PageDown'],
|
|
32
|
+
}
|
package/src/helpers.tsx
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { SizeTokens, getTokens, getVariableValue } from '@tamagui/core'
|
|
2
|
+
|
|
3
|
+
export function getNextSortedValues(prevValues: number[] = [], nextValue: number, atIndex: number) {
|
|
4
|
+
const nextValues = [...prevValues]
|
|
5
|
+
nextValues[atIndex] = nextValue
|
|
6
|
+
return nextValues.sort((a, b) => a - b)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function convertValueToPercentage(value: number, min: number, max: number) {
|
|
10
|
+
const maxSteps = max - min
|
|
11
|
+
const percentPerStep = 100 / maxSteps
|
|
12
|
+
return percentPerStep * (value - min)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Returns a label for each thumb when there are two or more thumbs
|
|
17
|
+
*/
|
|
18
|
+
export function getLabel(index: number, totalValues: number) {
|
|
19
|
+
if (totalValues > 2) {
|
|
20
|
+
return `Value ${index + 1} of ${totalValues}`
|
|
21
|
+
} else if (totalValues === 2) {
|
|
22
|
+
return ['Minimum', 'Maximum'][index]
|
|
23
|
+
} else {
|
|
24
|
+
return undefined
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Given a `values` array and a `nextValue`, determine which value in
|
|
30
|
+
* the array is closest to `nextValue` and return its index.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // returns 1
|
|
34
|
+
* getClosestValueIndex([10, 30], 25);
|
|
35
|
+
*/
|
|
36
|
+
export function getClosestValueIndex(values: number[], nextValue: number) {
|
|
37
|
+
if (values.length === 1) return 0
|
|
38
|
+
const distances = values.map((value) => Math.abs(value - nextValue))
|
|
39
|
+
const closestDistance = Math.min(...distances)
|
|
40
|
+
return distances.indexOf(closestDistance)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Offsets the thumb centre point while sliding to ensure it remains
|
|
45
|
+
* within the bounds of the slider when reaching the edges
|
|
46
|
+
*/
|
|
47
|
+
export function getThumbInBoundsOffset(width: number, left: number, direction: number) {
|
|
48
|
+
const halfWidth = width / 2
|
|
49
|
+
const halfPercent = 50
|
|
50
|
+
const offset = linearScale([0, halfPercent], [0, halfWidth])
|
|
51
|
+
return (halfWidth - offset(left) * direction) * direction
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Gets an array of steps between each value.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // returns [1, 9]
|
|
59
|
+
* getStepsBetweenValues([10, 11, 20]);
|
|
60
|
+
*/
|
|
61
|
+
function getStepsBetweenValues(values: number[]) {
|
|
62
|
+
return values.slice(0, -1).map((value, index) => values[index + 1] - value)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Verifies the minimum steps between all values is greater than or equal
|
|
67
|
+
* to the expected minimum steps.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // returns false
|
|
71
|
+
* hasMinStepsBetweenValues([1,2,3], 2);
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* // returns true
|
|
75
|
+
* hasMinStepsBetweenValues([1,2,3], 1);
|
|
76
|
+
*/
|
|
77
|
+
export function hasMinStepsBetweenValues(values: number[], minStepsBetweenValues: number) {
|
|
78
|
+
if (minStepsBetweenValues > 0) {
|
|
79
|
+
const stepsBetweenValues = getStepsBetweenValues(values)
|
|
80
|
+
const actualMinStepsBetweenValues = Math.min(...stepsBetweenValues)
|
|
81
|
+
return actualMinStepsBetweenValues >= minStepsBetweenValues
|
|
82
|
+
}
|
|
83
|
+
return true
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// https://github.com/tmcw-up-for-adoption/simple-linear-scale/blob/master/index.js
|
|
87
|
+
export function linearScale(input: readonly [number, number], output: readonly [number, number]) {
|
|
88
|
+
return (value: number) => {
|
|
89
|
+
if (input[0] === input[1] || output[0] === output[1]) return output[0]
|
|
90
|
+
const ratio = (output[1] - output[0]) / (input[1] - input[0])
|
|
91
|
+
return output[0] + ratio * (value - input[0])
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function getDecimalCount(value: number) {
|
|
96
|
+
return (String(value).split('.')[1] || '').length
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function roundValue(value: number, decimalCount: number) {
|
|
100
|
+
const rounder = Math.pow(10, decimalCount)
|
|
101
|
+
return Math.round(value * rounder) / rounder
|
|
102
|
+
}
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { GestureReponderEvent, SizeTokens } from '@tamagui/core'
|
|
2
|
+
import type { Scope } from '@tamagui/create-context'
|
|
3
|
+
import type { SizableStackProps } from '@tamagui/stacks'
|
|
4
|
+
import type { View } from 'react-native'
|
|
5
|
+
|
|
6
|
+
export type ScopedProps<P> = P & { __scopeSlider?: Scope }
|
|
7
|
+
|
|
8
|
+
export type Direction = 'ltr' | 'rtl'
|
|
9
|
+
|
|
10
|
+
export type SliderImplElement = HTMLElement | View
|
|
11
|
+
|
|
12
|
+
type SliderImplPrivateProps = {
|
|
13
|
+
onSlideStart(event: GestureReponderEvent, target: 'thumb' | 'track'): void
|
|
14
|
+
onSlideMove(event: GestureReponderEvent): void
|
|
15
|
+
onSlideEnd(event: GestureReponderEvent): void
|
|
16
|
+
onHomeKeyDown(event: React.KeyboardEvent): void
|
|
17
|
+
onEndKeyDown(event: React.KeyboardEvent): void
|
|
18
|
+
onStepKeyDown(event: React.KeyboardEvent): void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SliderTrackProps extends SizableStackProps {}
|
|
22
|
+
|
|
23
|
+
export interface SliderImplProps extends SliderTrackProps, SliderImplPrivateProps {
|
|
24
|
+
dir?: Direction
|
|
25
|
+
orientation: 'horizontal' | 'vertical'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type SliderOrientationPrivateProps = {
|
|
29
|
+
min: number
|
|
30
|
+
max: number
|
|
31
|
+
onSlideStart?(value: number, target: 'thumb' | 'track'): void
|
|
32
|
+
onSlideMove?(value: number): void
|
|
33
|
+
onHomeKeyDown(event: React.KeyboardEvent): void
|
|
34
|
+
onEndKeyDown(event: React.KeyboardEvent): void
|
|
35
|
+
onStepKeyDown(step: { event: React.KeyboardEvent; direction: number }): void
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface SliderOrientationProps
|
|
39
|
+
extends Omit<SliderImplProps, keyof SliderImplPrivateProps | 'orientation'>,
|
|
40
|
+
SliderOrientationPrivateProps {}
|
|
41
|
+
|
|
42
|
+
export interface SliderHorizontalProps extends SliderOrientationProps {
|
|
43
|
+
dir?: Direction
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface SliderVerticalProps extends SliderOrientationProps {
|
|
47
|
+
dir?: Direction
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface SliderProps
|
|
51
|
+
extends Omit<
|
|
52
|
+
SliderHorizontalProps | SliderVerticalProps,
|
|
53
|
+
keyof SliderOrientationPrivateProps | 'defaultValue'
|
|
54
|
+
> {
|
|
55
|
+
size?: SizeTokens
|
|
56
|
+
name?: string
|
|
57
|
+
disabled?: boolean
|
|
58
|
+
orientation?: React.AriaAttributes['aria-orientation']
|
|
59
|
+
dir?: Direction
|
|
60
|
+
min?: number
|
|
61
|
+
max?: number
|
|
62
|
+
step?: number
|
|
63
|
+
minStepsBetweenThumbs?: number
|
|
64
|
+
value?: number[]
|
|
65
|
+
defaultValue?: number[]
|
|
66
|
+
onValueChange?(value: number[]): void
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type SliderContextValue = {
|
|
70
|
+
size?: SizeTokens | number | null
|
|
71
|
+
disabled?: boolean
|
|
72
|
+
min: number
|
|
73
|
+
max: number
|
|
74
|
+
values: number[]
|
|
75
|
+
valueIndexToChangeRef: React.MutableRefObject<number>
|
|
76
|
+
thumbs: Set<any>
|
|
77
|
+
orientation: SliderProps['orientation']
|
|
78
|
+
}
|
package/types/Slider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../src/Slider.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAkB,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGhF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAmB,IAAI,EAAE,MAAM,cAAc,CAAA;AAwBpD,OAAO,EAIL,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAEjB,MAAM,SAAS,CAAA;AAMhB,aAAK,uBAAuB,GAAG,iBAAiB,CAAA;AAiEhD,aAAK,qBAAqB,GAAG,iBAAiB,CAAA;AAgE9C,aAAK,kBAAkB,GAAG,WAAW,GAAG,IAAI,CAAA;AAY5C,QAAA,MAAM,WAAW,6FAehB,CAAA;AAUD,aAAK,wBAAwB,GAAG,WAAW,GAAG,IAAI,CAAA;AAClD,UAAU,sBAAuB,SAAQ,WAAW;CAAG;AAQvD,QAAA,MAAM,iBAAiB,yGAqCtB,CAAA;AAqCD,aAAK,kBAAkB,GAAG,WAAW,GAAG,IAAI,CAAA;AAC5C,UAAU,gBAAiB,SAAQ,iBAAiB;IAClD,KAAK,EAAE,MAAM,CAAA;CACd;AAED,QAAA,MAAM,WAAW,6FAoFhB,CAAA;AAQD,aAAK,aAAa,GAAG,uBAAuB,GAAG,qBAAqB,CAAA;AAEpE,QAAA,MAAM,MAAM;;;;
|
|
1
|
+
{"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../src/Slider.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAkB,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGhF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAmB,IAAI,EAAE,MAAM,cAAc,CAAA;AAwBpD,OAAO,EAIL,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAEjB,MAAM,SAAS,CAAA;AAMhB,aAAK,uBAAuB,GAAG,iBAAiB,CAAA;AAiEhD,aAAK,qBAAqB,GAAG,iBAAiB,CAAA;AAgE9C,aAAK,kBAAkB,GAAG,WAAW,GAAG,IAAI,CAAA;AAY5C,QAAA,MAAM,WAAW,6FAehB,CAAA;AAUD,aAAK,wBAAwB,GAAG,WAAW,GAAG,IAAI,CAAA;AAClD,UAAU,sBAAuB,SAAQ,WAAW;CAAG;AAQvD,QAAA,MAAM,iBAAiB,yGAqCtB,CAAA;AAqCD,aAAK,kBAAkB,GAAG,WAAW,GAAG,IAAI,CAAA;AAC5C,UAAU,gBAAiB,SAAQ,iBAAiB;IAClD,KAAK,EAAE,MAAM,CAAA;CACd;AAED,QAAA,MAAM,WAAW,6FAoFhB,CAAA;AAQD,aAAK,aAAa,GAAG,uBAAuB,GAAG,qBAAqB,CAAA;AAEpE,QAAA,MAAM,MAAM;;;;CAsIX,CAAA;AAuCD,QAAA,MAAM,KAAK,6FAAc,CAAA;AACzB,QAAA,MAAM,KAAK,yGAAoB,CAAA;AAC/B,QAAA,MAAM,KAAK,6FAAc,CAAA;AAEzB,OAAO,EACL,MAAM,EACN,WAAW,EACX,iBAAiB,EACjB,WAAW,EAEX,KAAK,EACL,KAAK,EACL,KAAK,GACN,CAAA;AAED,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,CAAA"}
|