@tamagui/slider 1.0.1-beta.26
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 +390 -0
- package/dist/cjs/Slider.js.map +7 -0
- package/dist/cjs/SliderImpl.js +133 -0
- package/dist/cjs/SliderImpl.js.map +7 -0
- package/dist/cjs/context.js +50 -0
- package/dist/cjs/context.js.map +7 -0
- package/dist/cjs/helpers.js +120 -0
- package/dist/cjs/helpers.js.map +7 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/types.js +16 -0
- package/dist/cjs/types.js.map +7 -0
- package/dist/esm/Slider.js +338 -0
- package/dist/esm/Slider.js.map +7 -0
- package/dist/esm/SliderImpl.js +69 -0
- package/dist/esm/SliderImpl.js.map +7 -0
- package/dist/esm/context.js +21 -0
- package/dist/esm/context.js.map +7 -0
- package/dist/esm/helpers.js +89 -0
- package/dist/esm/helpers.js.map +7 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +7 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/types.js.map +7 -0
- package/dist/jsx/Slider.js +248 -0
- package/dist/jsx/SliderImpl.js +59 -0
- package/dist/jsx/context.js +20 -0
- package/dist/jsx/helpers.js +88 -0
- package/dist/jsx/index.js +2 -0
- package/dist/jsx/types.js +0 -0
- package/package.json +44 -0
- package/types/Slider.d.ts +29 -0
- package/types/Slider.d.ts.map +1 -0
- package/types/SliderImpl.d.ts +54 -0
- package/types/SliderImpl.d.ts.map +1 -0
- package/types/context.d.ts +50 -0
- package/types/context.d.ts.map +1 -0
- package/types/helpers.d.ts +12 -0
- package/types/helpers.d.ts.map +1 -0
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +1 -0
- package/types/types.d.ts +70 -0
- package/types/types.d.ts.map +1 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/SliderImpl.tsx"],
|
|
4
|
+
"sourcesContent": ["/* -------------------------------------------------------------------------------------------------\n * SliderImpl\n * -----------------------------------------------------------------------------------------------*/\n\nimport { composeEventHandlers, styled } from '@tamagui/core'\nimport { YStack, getCircleSize } from '@tamagui/stacks'\nimport * as React from 'react'\n\nimport { SLIDER_NAME, useSliderContext } from './context'\nimport { ScopedProps, SliderImplElement, SliderImplProps } from './types'\n\nexport const DirectionalYStack = styled(YStack, {\n variants: {\n orientation: {\n horizontal: {},\n vertical: {},\n },\n },\n})\n\nexport const SliderFrame = styled(DirectionalYStack, {\n name: 'Slider',\n position: 'relative',\n\n variants: {\n size: (val, extras) => {\n const orientation = extras.props.orientation\n const circleSize = getCircleSize(val, extras)\n const size = circleSize / 4\n if (orientation === 'horizontal') {\n return {\n height: size,\n width: 100,\n }\n }\n return {\n width: size,\n height: 100,\n }\n },\n },\n})\n\nexport const SliderImpl = React.forwardRef<SliderImplElement, SliderImplProps>(\n (props: ScopedProps<SliderImplProps>, forwardedRef) => {\n const {\n __scopeSlider,\n onSlideStart,\n onSlideMove,\n onSlideEnd,\n onHomeKeyDown,\n onEndKeyDown,\n onStepKeyDown,\n ...sliderProps\n } = props\n const context = useSliderContext(SLIDER_NAME, __scopeSlider)\n\n return (\n <SliderFrame\n size=\"$4\"\n {...sliderProps}\n data-orientation={sliderProps.orientation}\n ref={forwardedRef}\n // onKeyDown={composeEventHandlers(props.onKeyDown, (event) => {\n // if (event.key === 'Home') {\n // onHomeKeyDown(event)\n // // Prevent scrolling to page start\n // event.preventDefault()\n // } else if (event.key === 'End') {\n // onEndKeyDown(event)\n // // Prevent scrolling to page end\n // event.preventDefault()\n // } else if (PAGE_KEYS.concat(ARROW_KEYS).includes(event.key)) {\n // onStepKeyDown(event)\n // // Prevent scrolling for directional key presses\n // event.preventDefault()\n // }\n // })}\n onStartShouldSetResponder={() => true}\n onResponderGrant={composeEventHandlers(props.onResponderGrant, (event) => {\n // const target = event.target as HTMLElement\n // console.log('wut', target)\n // target.setPointerCapture(event.pointerId)\n // // Prevent browser focus behaviour because we focus a thumb manually when values change.\n event.preventDefault()\n // Touch devices have a delay before focusing so won't focus if touch immediately moves\n // away from target (sliding). We want thumb to focus regardless.\n // if (context.thumbs.has(target)) {\n // target.focus()\n // } else {\n onSlideStart(event)\n // }\n })}\n onResponderMove={composeEventHandlers(props.onResponderMove, (event) => {\n // const target = event.target as HTMLElement\n onSlideMove(event)\n })}\n onResponderRelease={composeEventHandlers(props.onResponderRelease, (event) => {\n // const target = event.target as HTMLElement\n onSlideEnd(event)\n })}\n />\n )\n }\n)\n"],
|
|
5
|
+
"mappings": "AAIA;AACA;AACA;AAEA;AAGO,MAAM,oBAAoB,OAAO,QAAQ;AAAA,EAC9C,UAAU;AAAA,IACR,aAAa;AAAA,MACX,YAAY,CAAC;AAAA,MACb,UAAU,CAAC;AAAA,IACb;AAAA,EACF;AACF,CAAC;AAEM,MAAM,cAAc,OAAO,mBAAmB;AAAA,EACnD,MAAM;AAAA,EACN,UAAU;AAAA,EAEV,UAAU;AAAA,IACR,MAAM,CAAC,KAAK,WAAW;AACrB,YAAM,cAAc,OAAO,MAAM;AACjC,YAAM,aAAa,cAAc,KAAK,MAAM;AAC5C,YAAM,OAAO,aAAa;AAC1B,UAAI,gBAAgB,cAAc;AAChC,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAEM,MAAM,aAAa,MAAM,WAC9B,CAAC,OAAqC,iBAAiB;AACrD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,OACG;AAAA,MACD;AACJ,QAAM,UAAU,iBAAiB,aAAa,aAAa;AAE3D,SACE,oCAAC;AAAA,IACC,MAAK;AAAA,OACD;AAAA,IACJ,oBAAkB,YAAY;AAAA,IAC9B,KAAK;AAAA,IAgBL,2BAA2B,MAAM;AAAA,IACjC,kBAAkB,qBAAqB,MAAM,kBAAkB,CAAC,UAAU;AAKxE,YAAM,eAAe;AAMrB,mBAAa,KAAK;AAAA,IAEpB,CAAC;AAAA,IACD,iBAAiB,qBAAqB,MAAM,iBAAiB,CAAC,UAAU;AAEtE,kBAAY,KAAK;AAAA,IACnB,CAAC;AAAA,IACD,oBAAoB,qBAAqB,MAAM,oBAAoB,CAAC,UAAU;AAE5E,iBAAW,KAAK;AAAA,IAClB,CAAC;AAAA,GACH;AAEJ,CACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createContextScope } from "@tamagui/create-context";
|
|
2
|
+
const SLIDER_NAME = "Slider";
|
|
3
|
+
const [createSliderContext, createSliderScope] = createContextScope(SLIDER_NAME);
|
|
4
|
+
const [SliderProvider, useSliderContext] = createSliderContext(SLIDER_NAME);
|
|
5
|
+
const [SliderOrientationProvider, useSliderOrientationContext] = createSliderContext(SLIDER_NAME, {
|
|
6
|
+
startEdge: "left",
|
|
7
|
+
endEdge: "right",
|
|
8
|
+
sizeProp: "width",
|
|
9
|
+
size: 0,
|
|
10
|
+
direction: 1
|
|
11
|
+
});
|
|
12
|
+
export {
|
|
13
|
+
SLIDER_NAME,
|
|
14
|
+
SliderOrientationProvider,
|
|
15
|
+
SliderProvider,
|
|
16
|
+
createSliderContext,
|
|
17
|
+
createSliderScope,
|
|
18
|
+
useSliderContext,
|
|
19
|
+
useSliderOrientationContext
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/context.tsx"],
|
|
4
|
+
"sourcesContent": ["import { SizeTokens } from '@tamagui/core'\nimport { createContextScope } from '@tamagui/create-context'\n\nimport { SliderContextValue } from './types'\n\nexport const SLIDER_NAME = 'Slider'\n\nexport const [createSliderContext, createSliderScope] = createContextScope(SLIDER_NAME)\n\nexport const [SliderProvider, useSliderContext] =\n createSliderContext<SliderContextValue>(SLIDER_NAME)\n\nexport const [SliderOrientationProvider, useSliderOrientationContext] = createSliderContext<{\n startEdge: 'bottom' | 'left' | 'right'\n endEdge: 'top' | 'right' | 'left'\n sizeProp: 'width' | 'height'\n size: number | SizeTokens\n direction: number\n}>(SLIDER_NAME, {\n startEdge: 'left',\n endEdge: 'right',\n sizeProp: 'width',\n size: 0,\n direction: 1,\n})\n"],
|
|
5
|
+
"mappings": "AACA;AAIO,MAAM,cAAc;AAEpB,MAAM,CAAC,qBAAqB,qBAAqB,mBAAmB,WAAW;AAE/E,MAAM,CAAC,gBAAgB,oBAC5B,oBAAwC,WAAW;AAE9C,MAAM,CAAC,2BAA2B,+BAA+B,oBAMrE,aAAa;AAAA,EACd,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AACb,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { getTokens, getVariableValue } from "@tamagui/core";
|
|
4
|
+
function getNextSortedValues(prevValues = [], nextValue, atIndex) {
|
|
5
|
+
const nextValues = [...prevValues];
|
|
6
|
+
nextValues[atIndex] = nextValue;
|
|
7
|
+
return nextValues.sort((a, b) => a - b);
|
|
8
|
+
}
|
|
9
|
+
__name(getNextSortedValues, "getNextSortedValues");
|
|
10
|
+
function convertValueToPercentage(value, min, max) {
|
|
11
|
+
const maxSteps = max - min;
|
|
12
|
+
const percentPerStep = 100 / maxSteps;
|
|
13
|
+
return percentPerStep * (value - min);
|
|
14
|
+
}
|
|
15
|
+
__name(convertValueToPercentage, "convertValueToPercentage");
|
|
16
|
+
function getLabel(index, totalValues) {
|
|
17
|
+
if (totalValues > 2) {
|
|
18
|
+
return `Value ${index + 1} of ${totalValues}`;
|
|
19
|
+
} else if (totalValues === 2) {
|
|
20
|
+
return ["Minimum", "Maximum"][index];
|
|
21
|
+
} else {
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
__name(getLabel, "getLabel");
|
|
26
|
+
function getClosestValueIndex(values, nextValue) {
|
|
27
|
+
if (values.length === 1)
|
|
28
|
+
return 0;
|
|
29
|
+
const distances = values.map((value) => Math.abs(value - nextValue));
|
|
30
|
+
const closestDistance = Math.min(...distances);
|
|
31
|
+
return distances.indexOf(closestDistance);
|
|
32
|
+
}
|
|
33
|
+
__name(getClosestValueIndex, "getClosestValueIndex");
|
|
34
|
+
function getThumbInBoundsOffset(width, left, direction) {
|
|
35
|
+
const halfWidth = width / 2;
|
|
36
|
+
const halfPercent = 50;
|
|
37
|
+
const offset = linearScale([0, halfPercent], [0, halfWidth]);
|
|
38
|
+
return (halfWidth - offset(left) * direction) * direction;
|
|
39
|
+
}
|
|
40
|
+
__name(getThumbInBoundsOffset, "getThumbInBoundsOffset");
|
|
41
|
+
function getStepsBetweenValues(values) {
|
|
42
|
+
return values.slice(0, -1).map((value, index) => values[index + 1] - value);
|
|
43
|
+
}
|
|
44
|
+
__name(getStepsBetweenValues, "getStepsBetweenValues");
|
|
45
|
+
function hasMinStepsBetweenValues(values, minStepsBetweenValues) {
|
|
46
|
+
if (minStepsBetweenValues > 0) {
|
|
47
|
+
const stepsBetweenValues = getStepsBetweenValues(values);
|
|
48
|
+
const actualMinStepsBetweenValues = Math.min(...stepsBetweenValues);
|
|
49
|
+
return actualMinStepsBetweenValues >= minStepsBetweenValues;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
__name(hasMinStepsBetweenValues, "hasMinStepsBetweenValues");
|
|
54
|
+
function linearScale(input, output) {
|
|
55
|
+
return (value) => {
|
|
56
|
+
if (input[0] === input[1] || output[0] === output[1])
|
|
57
|
+
return output[0];
|
|
58
|
+
const ratio = (output[1] - output[0]) / (input[1] - input[0]);
|
|
59
|
+
return output[0] + ratio * (value - input[0]);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
__name(linearScale, "linearScale");
|
|
63
|
+
function getDecimalCount(value) {
|
|
64
|
+
return (String(value).split(".")[1] || "").length;
|
|
65
|
+
}
|
|
66
|
+
__name(getDecimalCount, "getDecimalCount");
|
|
67
|
+
function roundValue(value, decimalCount) {
|
|
68
|
+
const rounder = Math.pow(10, decimalCount);
|
|
69
|
+
return Math.round(value * rounder) / rounder;
|
|
70
|
+
}
|
|
71
|
+
__name(roundValue, "roundValue");
|
|
72
|
+
function getSize(size) {
|
|
73
|
+
const tokens = getTokens();
|
|
74
|
+
return typeof size === "number" ? size : size ? getVariableValue(tokens.size[size]) : null;
|
|
75
|
+
}
|
|
76
|
+
__name(getSize, "getSize");
|
|
77
|
+
export {
|
|
78
|
+
convertValueToPercentage,
|
|
79
|
+
getClosestValueIndex,
|
|
80
|
+
getDecimalCount,
|
|
81
|
+
getLabel,
|
|
82
|
+
getNextSortedValues,
|
|
83
|
+
getSize,
|
|
84
|
+
getThumbInBoundsOffset,
|
|
85
|
+
hasMinStepsBetweenValues,
|
|
86
|
+
linearScale,
|
|
87
|
+
roundValue
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/helpers.tsx"],
|
|
4
|
+
"sourcesContent": ["import { SizeTokens, getTokens, getVariableValue } from '@tamagui/core'\n\nexport function getNextSortedValues(prevValues: number[] = [], nextValue: number, atIndex: number) {\n const nextValues = [...prevValues]\n nextValues[atIndex] = nextValue\n return nextValues.sort((a, b) => a - b)\n}\n\nexport function convertValueToPercentage(value: number, min: number, max: number) {\n const maxSteps = max - min\n const percentPerStep = 100 / maxSteps\n return percentPerStep * (value - min)\n}\n\n/**\n * Returns a label for each thumb when there are two or more thumbs\n */\nexport function getLabel(index: number, totalValues: number) {\n if (totalValues > 2) {\n return `Value ${index + 1} of ${totalValues}`\n } else if (totalValues === 2) {\n return ['Minimum', 'Maximum'][index]\n } else {\n return undefined\n }\n}\n\n/**\n * Given a `values` array and a `nextValue`, determine which value in\n * the array is closest to `nextValue` and return its index.\n *\n * @example\n * // returns 1\n * getClosestValueIndex([10, 30], 25);\n */\nexport function getClosestValueIndex(values: number[], nextValue: number) {\n if (values.length === 1) return 0\n const distances = values.map((value) => Math.abs(value - nextValue))\n const closestDistance = Math.min(...distances)\n return distances.indexOf(closestDistance)\n}\n\n/**\n * Offsets the thumb centre point while sliding to ensure it remains\n * within the bounds of the slider when reaching the edges\n */\nexport function getThumbInBoundsOffset(width: number, left: number, direction: number) {\n const halfWidth = width / 2\n const halfPercent = 50\n const offset = linearScale([0, halfPercent], [0, halfWidth])\n return (halfWidth - offset(left) * direction) * direction\n}\n\n/**\n * Gets an array of steps between each value.\n *\n * @example\n * // returns [1, 9]\n * getStepsBetweenValues([10, 11, 20]);\n */\nfunction getStepsBetweenValues(values: number[]) {\n return values.slice(0, -1).map((value, index) => values[index + 1] - value)\n}\n\n/**\n * Verifies the minimum steps between all values is greater than or equal\n * to the expected minimum steps.\n *\n * @example\n * // returns false\n * hasMinStepsBetweenValues([1,2,3], 2);\n *\n * @example\n * // returns true\n * hasMinStepsBetweenValues([1,2,3], 1);\n */\nexport function hasMinStepsBetweenValues(values: number[], minStepsBetweenValues: number) {\n if (minStepsBetweenValues > 0) {\n const stepsBetweenValues = getStepsBetweenValues(values)\n const actualMinStepsBetweenValues = Math.min(...stepsBetweenValues)\n return actualMinStepsBetweenValues >= minStepsBetweenValues\n }\n return true\n}\n\n// https://github.com/tmcw-up-for-adoption/simple-linear-scale/blob/master/index.js\nexport function linearScale(input: readonly [number, number], output: readonly [number, number]) {\n return (value: number) => {\n if (input[0] === input[1] || output[0] === output[1]) return output[0]\n const ratio = (output[1] - output[0]) / (input[1] - input[0])\n return output[0] + ratio * (value - input[0])\n }\n}\n\nexport function getDecimalCount(value: number) {\n return (String(value).split('.')[1] || '').length\n}\n\nexport function roundValue(value: number, decimalCount: number) {\n const rounder = Math.pow(10, decimalCount)\n return Math.round(value * rounder) / rounder\n}\n\nexport function getSize(size?: SizeTokens) {\n const tokens = getTokens()\n return typeof size === 'number'\n ? size\n : size\n ? (getVariableValue(tokens.size[size]) as number)\n : null\n}\n"],
|
|
5
|
+
"mappings": ";;AAAA;AAEO,6BAA6B,aAAuB,CAAC,GAAG,WAAmB,SAAiB;AACjG,QAAM,aAAa,CAAC,GAAG,UAAU;AACjC,aAAW,WAAW;AACtB,SAAO,WAAW,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACxC;AAJgB;AAMT,kCAAkC,OAAe,KAAa,KAAa;AAChF,QAAM,WAAW,MAAM;AACvB,QAAM,iBAAiB,MAAM;AAC7B,SAAO,iBAAkB,SAAQ;AACnC;AAJgB;AAST,kBAAkB,OAAe,aAAqB;AAC3D,MAAI,cAAc,GAAG;AACnB,WAAO,SAAS,QAAQ,QAAQ;AAAA,EAClC,WAAW,gBAAgB,GAAG;AAC5B,WAAO,CAAC,WAAW,SAAS,EAAE;AAAA,EAChC,OAAO;AACL,WAAO;AAAA,EACT;AACF;AARgB;AAkBT,8BAA8B,QAAkB,WAAmB;AACxE,MAAI,OAAO,WAAW;AAAG,WAAO;AAChC,QAAM,YAAY,OAAO,IAAI,CAAC,UAAU,KAAK,IAAI,QAAQ,SAAS,CAAC;AACnE,QAAM,kBAAkB,KAAK,IAAI,GAAG,SAAS;AAC7C,SAAO,UAAU,QAAQ,eAAe;AAC1C;AALgB;AAWT,gCAAgC,OAAe,MAAc,WAAmB;AACrF,QAAM,YAAY,QAAQ;AAC1B,QAAM,cAAc;AACpB,QAAM,SAAS,YAAY,CAAC,GAAG,WAAW,GAAG,CAAC,GAAG,SAAS,CAAC;AAC3D,SAAQ,aAAY,OAAO,IAAI,IAAI,aAAa;AAClD;AALgB;AAchB,+BAA+B,QAAkB;AAC/C,SAAO,OAAO,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,OAAO,UAAU,OAAO,QAAQ,KAAK,KAAK;AAC5E;AAFS;AAgBF,kCAAkC,QAAkB,uBAA+B;AACxF,MAAI,wBAAwB,GAAG;AAC7B,UAAM,qBAAqB,sBAAsB,MAAM;AACvD,UAAM,8BAA8B,KAAK,IAAI,GAAG,kBAAkB;AAClE,WAAO,+BAA+B;AAAA,EACxC;AACA,SAAO;AACT;AAPgB;AAUT,qBAAqB,OAAkC,QAAmC;AAC/F,SAAO,CAAC,UAAkB;AACxB,QAAI,MAAM,OAAO,MAAM,MAAM,OAAO,OAAO,OAAO;AAAI,aAAO,OAAO;AACpE,UAAM,QAAS,QAAO,KAAK,OAAO,MAAO,OAAM,KAAK,MAAM;AAC1D,WAAO,OAAO,KAAK,QAAS,SAAQ,MAAM;AAAA,EAC5C;AACF;AANgB;AAQT,yBAAyB,OAAe;AAC7C,SAAQ,QAAO,KAAK,EAAE,MAAM,GAAG,EAAE,MAAM,IAAI;AAC7C;AAFgB;AAIT,oBAAoB,OAAe,cAAsB;AAC9D,QAAM,UAAU,KAAK,IAAI,IAAI,YAAY;AACzC,SAAO,KAAK,MAAM,QAAQ,OAAO,IAAI;AACvC;AAHgB;AAKT,iBAAiB,MAAmB;AACzC,QAAM,SAAS,UAAU;AACzB,SAAO,OAAO,SAAS,WACnB,OACA,OACC,iBAAiB,OAAO,KAAK,KAAK,IACnC;AACN;AAPgB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { usePrevious } from "@radix-ui/react-use-previous";
|
|
4
|
+
import { useComposedRefs } from "@tamagui/compose-refs";
|
|
5
|
+
import { styled, withStaticProperties } from "@tamagui/core";
|
|
6
|
+
import { clamp, composeEventHandlers } from "@tamagui/helpers";
|
|
7
|
+
import { SizableStack } from "@tamagui/stacks";
|
|
8
|
+
import { useControllableState } from "@tamagui/use-controllable-state";
|
|
9
|
+
import { useDirection } from "@tamagui/use-direction";
|
|
10
|
+
import * as React from "react";
|
|
11
|
+
import {
|
|
12
|
+
SLIDER_NAME,
|
|
13
|
+
SliderOrientationProvider,
|
|
14
|
+
SliderProvider,
|
|
15
|
+
useSliderContext,
|
|
16
|
+
useSliderOrientationContext
|
|
17
|
+
} from "./context";
|
|
18
|
+
import {
|
|
19
|
+
convertValueToPercentage,
|
|
20
|
+
getClosestValueIndex,
|
|
21
|
+
getDecimalCount,
|
|
22
|
+
getLabel,
|
|
23
|
+
getNextSortedValues,
|
|
24
|
+
getThumbInBoundsOffset,
|
|
25
|
+
hasMinStepsBetweenValues,
|
|
26
|
+
linearScale,
|
|
27
|
+
roundValue
|
|
28
|
+
} from "./helpers";
|
|
29
|
+
import { SliderFrame, SliderImpl } from "./SliderImpl";
|
|
30
|
+
const PAGE_KEYS = ["PageUp", "PageDown"];
|
|
31
|
+
const ARROW_KEYS = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"];
|
|
32
|
+
const BACK_KEYS = {
|
|
33
|
+
ltr: ["ArrowDown", "Home", "ArrowLeft", "PageDown"],
|
|
34
|
+
rtl: ["ArrowDown", "Home", "ArrowRight", "PageDown"]
|
|
35
|
+
};
|
|
36
|
+
const SliderHorizontal = React.forwardRef((props, forwardedRef) => {
|
|
37
|
+
const { min, max, dir, onSlideStart, onSlideMove, onStepKeyDown, ...sliderProps } = props;
|
|
38
|
+
const layoutRef = React.useRef(null);
|
|
39
|
+
const direction = useDirection(dir);
|
|
40
|
+
const isDirectionLTR = direction === "ltr";
|
|
41
|
+
const [size, setSize] = React.useState(0);
|
|
42
|
+
function getValueFromPointer(pointerPosition) {
|
|
43
|
+
const layout = layoutRef.current;
|
|
44
|
+
if (!layout)
|
|
45
|
+
return;
|
|
46
|
+
const input = [0, layout.width];
|
|
47
|
+
const output = isDirectionLTR ? [min, max] : [max, min];
|
|
48
|
+
const value = linearScale(input, output);
|
|
49
|
+
return value(pointerPosition - layout.x);
|
|
50
|
+
}
|
|
51
|
+
__name(getValueFromPointer, "getValueFromPointer");
|
|
52
|
+
return <SliderOrientationProvider scope={props.__scopeSlider} startEdge={isDirectionLTR ? "left" : "right"} endEdge={isDirectionLTR ? "right" : "left"} direction={isDirectionLTR ? 1 : -1} sizeProp="width" size={size}><SliderImpl dir={direction} orientation="horizontal" {...sliderProps} onLayout={(e) => {
|
|
53
|
+
const layout = e.nativeEvent.layout;
|
|
54
|
+
layoutRef.current = layout;
|
|
55
|
+
setSize(layout.height);
|
|
56
|
+
}} ref={forwardedRef} onSlideStart={(event) => {
|
|
57
|
+
const value = getValueFromPointer(event.nativeEvent.pageX);
|
|
58
|
+
if (value) {
|
|
59
|
+
onSlideStart == null ? void 0 : onSlideStart(value);
|
|
60
|
+
}
|
|
61
|
+
}} onSlideMove={(event) => {
|
|
62
|
+
const value = getValueFromPointer(event.nativeEvent.pageX);
|
|
63
|
+
if (value) {
|
|
64
|
+
onSlideMove == null ? void 0 : onSlideMove(value);
|
|
65
|
+
}
|
|
66
|
+
}} onSlideEnd={() => {
|
|
67
|
+
}} onStepKeyDown={(event) => {
|
|
68
|
+
const isBackKey = BACK_KEYS[direction].includes(event.key);
|
|
69
|
+
onStepKeyDown == null ? void 0 : onStepKeyDown({ event, direction: isBackKey ? -1 : 1 });
|
|
70
|
+
}} /></SliderOrientationProvider>;
|
|
71
|
+
});
|
|
72
|
+
const SliderVertical = React.forwardRef((props, forwardedRef) => {
|
|
73
|
+
const { min, max, onSlideStart, onSlideMove, onStepKeyDown, ...sliderProps } = props;
|
|
74
|
+
const sliderRef = React.useRef(null);
|
|
75
|
+
const ref = useComposedRefs(forwardedRef, sliderRef);
|
|
76
|
+
const rectRef = React.useRef();
|
|
77
|
+
function getValueFromPointer(pointerPosition) {
|
|
78
|
+
const rect = rectRef.current || sliderRef.current.getBoundingClientRect();
|
|
79
|
+
const input = [0, rect.height];
|
|
80
|
+
const output = [max, min];
|
|
81
|
+
const value = linearScale(input, output);
|
|
82
|
+
rectRef.current = rect;
|
|
83
|
+
return value(pointerPosition - rect.top);
|
|
84
|
+
}
|
|
85
|
+
__name(getValueFromPointer, "getValueFromPointer");
|
|
86
|
+
return <SliderOrientationProvider scope={props.__scopeSlider} startEdge="bottom" endEdge="top" sizeProp="height" size={0} direction={1}><SliderImpl {...sliderProps} orientation="vertical" ref={ref} onSlideStart={(event) => {
|
|
87
|
+
const value = getValueFromPointer(event.nativeEvent.locationY);
|
|
88
|
+
onSlideStart == null ? void 0 : onSlideStart(value);
|
|
89
|
+
}} onSlideMove={(event) => {
|
|
90
|
+
const value = getValueFromPointer(event.nativeEvent.locationY);
|
|
91
|
+
onSlideMove == null ? void 0 : onSlideMove(value);
|
|
92
|
+
}} onSlideEnd={() => rectRef.current = void 0} onStepKeyDown={(event) => {
|
|
93
|
+
const isBackKey = BACK_KEYS.ltr.includes(event.key);
|
|
94
|
+
onStepKeyDown == null ? void 0 : onStepKeyDown({ event, direction: isBackKey ? -1 : 1 });
|
|
95
|
+
}} /></SliderOrientationProvider>;
|
|
96
|
+
});
|
|
97
|
+
const TRACK_NAME = "SliderTrack";
|
|
98
|
+
const SliderTrackFrame = styled(SliderFrame, {
|
|
99
|
+
name: "SliderTrackFrame"
|
|
100
|
+
});
|
|
101
|
+
const SliderTrack = React.forwardRef((props, forwardedRef) => {
|
|
102
|
+
const { __scopeSlider, ...trackProps } = props;
|
|
103
|
+
const context = useSliderContext(TRACK_NAME, __scopeSlider);
|
|
104
|
+
return <SliderTrackFrame data-disabled={context.disabled ? "" : void 0} data-orientation={context.orientation} orientation={context.orientation} {...trackProps} ref={forwardedRef} />;
|
|
105
|
+
});
|
|
106
|
+
SliderTrack.displayName = TRACK_NAME;
|
|
107
|
+
const RANGE_NAME = "SliderTrackActive";
|
|
108
|
+
const SliderTrackActiveFrame = styled(SliderFrame, {
|
|
109
|
+
name: "SliderTrackActive"
|
|
110
|
+
});
|
|
111
|
+
const SliderTrackActive = React.forwardRef((props, forwardedRef) => {
|
|
112
|
+
const { __scopeSlider, ...rangeProps } = props;
|
|
113
|
+
const context = useSliderContext(RANGE_NAME, __scopeSlider);
|
|
114
|
+
const orientation = useSliderOrientationContext(RANGE_NAME, __scopeSlider);
|
|
115
|
+
const ref = React.useRef(null);
|
|
116
|
+
const composedRefs = useComposedRefs(forwardedRef, ref);
|
|
117
|
+
const valuesCount = context.values.length;
|
|
118
|
+
const percentages = context.values.map((value) => convertValueToPercentage(value, context.min, context.max));
|
|
119
|
+
const offsetStart = valuesCount > 1 ? Math.min(...percentages) : 0;
|
|
120
|
+
const offsetEnd = 100 - Math.max(...percentages);
|
|
121
|
+
return <SliderTrackActiveFrame orientation={context.orientation} data-orientation={context.orientation} data-disabled={context.disabled ? "" : void 0} {...rangeProps} ref={composedRefs} {...{
|
|
122
|
+
[orientation.startEdge]: offsetStart + "%",
|
|
123
|
+
[orientation.endEdge]: offsetEnd + "%"
|
|
124
|
+
}} />;
|
|
125
|
+
});
|
|
126
|
+
SliderTrackActive.displayName = RANGE_NAME;
|
|
127
|
+
const THUMB_NAME = "SliderThumb";
|
|
128
|
+
const SliderThumbFrame = styled(SizableStack, {
|
|
129
|
+
name: "SliderThumb",
|
|
130
|
+
position: "absolute"
|
|
131
|
+
});
|
|
132
|
+
const SliderThumb = React.forwardRef((props, forwardedRef) => {
|
|
133
|
+
var _a;
|
|
134
|
+
const { __scopeSlider, index, size: sizeProp, ...thumbProps } = props;
|
|
135
|
+
const context = useSliderContext(THUMB_NAME, __scopeSlider);
|
|
136
|
+
const orientation = useSliderOrientationContext(THUMB_NAME, __scopeSlider);
|
|
137
|
+
const value = context.values[index];
|
|
138
|
+
const percent = value === void 0 ? 0 : convertValueToPercentage(value, context.min, context.max);
|
|
139
|
+
const label = getLabel(index, context.values.length);
|
|
140
|
+
const [size, setSize] = React.useState(0);
|
|
141
|
+
const thumbInBoundsOffset = size ? getThumbInBoundsOffset(size, percent, orientation.direction) : 0;
|
|
142
|
+
console.log("thumbInBoundsOffset", thumbInBoundsOffset, size, percent);
|
|
143
|
+
return <SliderThumbFrame ref={forwardedRef} aria-label={props["aria-label"] || label} aria-valuemin={context.min} aria-valuenow={value} aria-valuemax={context.max} aria-orientation={context.orientation} data-orientation={context.orientation} data-disabled={context.disabled ? "" : void 0} {...thumbProps} x={thumbInBoundsOffset} y={-size / 2} size={(_a = sizeProp != null ? sizeProp : context.size) != null ? _a : 30} onLayout={(e) => {
|
|
144
|
+
setSize(e.nativeEvent.layout[orientation.sizeProp]);
|
|
145
|
+
}} {...{
|
|
146
|
+
[orientation.startEdge]: `${percent}%`
|
|
147
|
+
}} style={value === void 0 ? { display: "none" } : props.style} onFocus={composeEventHandlers(props.onFocus, () => {
|
|
148
|
+
context.valueIndexToChangeRef.current = index;
|
|
149
|
+
})} />;
|
|
150
|
+
});
|
|
151
|
+
SliderThumb.displayName = THUMB_NAME;
|
|
152
|
+
const Slider = withStaticProperties(React.forwardRef((props, forwardedRef) => {
|
|
153
|
+
const {
|
|
154
|
+
name,
|
|
155
|
+
min = 0,
|
|
156
|
+
max = 100,
|
|
157
|
+
step = 1,
|
|
158
|
+
orientation = "horizontal",
|
|
159
|
+
disabled = false,
|
|
160
|
+
minStepsBetweenThumbs = 0,
|
|
161
|
+
defaultValue = [min],
|
|
162
|
+
value,
|
|
163
|
+
onValueChange = /* @__PURE__ */ __name(() => {
|
|
164
|
+
}, "onValueChange"),
|
|
165
|
+
size: sizeProp,
|
|
166
|
+
...sliderProps
|
|
167
|
+
} = props;
|
|
168
|
+
const thumbRefs = React.useRef(/* @__PURE__ */ new Set());
|
|
169
|
+
const valueIndexToChangeRef = React.useRef(0);
|
|
170
|
+
const isHorizontal = orientation === "horizontal";
|
|
171
|
+
const [values = [], setValues] = useControllableState({
|
|
172
|
+
prop: value,
|
|
173
|
+
defaultProp: defaultValue,
|
|
174
|
+
onChange: (value2) => {
|
|
175
|
+
onValueChange(value2);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
function handleSlideStart(value2) {
|
|
179
|
+
const closestIndex = getClosestValueIndex(values, value2);
|
|
180
|
+
updateValues(value2, closestIndex);
|
|
181
|
+
}
|
|
182
|
+
__name(handleSlideStart, "handleSlideStart");
|
|
183
|
+
function handleSlideMove(value2) {
|
|
184
|
+
updateValues(value2, valueIndexToChangeRef.current);
|
|
185
|
+
}
|
|
186
|
+
__name(handleSlideMove, "handleSlideMove");
|
|
187
|
+
function updateValues(value2, atIndex) {
|
|
188
|
+
const decimalCount = getDecimalCount(step);
|
|
189
|
+
const snapToStep = roundValue(Math.round((value2 - min) / step) * step + min, decimalCount);
|
|
190
|
+
const nextValue = clamp(snapToStep, [min, max]);
|
|
191
|
+
setValues((prevValues = []) => {
|
|
192
|
+
const nextValues = getNextSortedValues(prevValues, nextValue, atIndex);
|
|
193
|
+
if (hasMinStepsBetweenValues(nextValues, minStepsBetweenThumbs * step)) {
|
|
194
|
+
valueIndexToChangeRef.current = nextValues.indexOf(nextValue);
|
|
195
|
+
return String(nextValues) === String(prevValues) ? prevValues : nextValues;
|
|
196
|
+
} else {
|
|
197
|
+
return prevValues;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
__name(updateValues, "updateValues");
|
|
202
|
+
const SliderOriented = isHorizontal ? SliderHorizontal : SliderVertical;
|
|
203
|
+
return <SliderProvider scope={props.__scopeSlider} disabled={disabled} min={min} max={max} valueIndexToChangeRef={valueIndexToChangeRef} thumbs={thumbRefs.current} values={values} orientation={orientation} size={sizeProp || 20}><SliderOriented aria-disabled={disabled} data-disabled={disabled ? "" : void 0} {...sliderProps} ref={forwardedRef} min={min} max={max} onSlideStart={disabled ? void 0 : handleSlideStart} onSlideMove={disabled ? void 0 : handleSlideMove} onHomeKeyDown={() => !disabled && updateValues(min, 0)} onEndKeyDown={() => !disabled && updateValues(max, values.length - 1)} onStepKeyDown={({ event, direction: stepDirection }) => {
|
|
204
|
+
if (!disabled) {
|
|
205
|
+
const isPageKey = PAGE_KEYS.includes(event.key);
|
|
206
|
+
const isSkipKey = isPageKey || event.shiftKey && ARROW_KEYS.includes(event.key);
|
|
207
|
+
const multiplier = isSkipKey ? 10 : 1;
|
|
208
|
+
const atIndex = valueIndexToChangeRef.current;
|
|
209
|
+
const value2 = values[atIndex];
|
|
210
|
+
const stepInDirection = step * multiplier * stepDirection;
|
|
211
|
+
updateValues(value2 + stepInDirection, atIndex);
|
|
212
|
+
}
|
|
213
|
+
}} /></SliderProvider>;
|
|
214
|
+
}), {
|
|
215
|
+
Track: SliderTrack,
|
|
216
|
+
TrackActive: SliderTrackActive,
|
|
217
|
+
Thumb: SliderThumb
|
|
218
|
+
});
|
|
219
|
+
Slider.displayName = SLIDER_NAME;
|
|
220
|
+
const BubbleInput = /* @__PURE__ */ __name((props) => {
|
|
221
|
+
const { value, ...inputProps } = props;
|
|
222
|
+
const ref = React.useRef(null);
|
|
223
|
+
const prevValue = usePrevious(value);
|
|
224
|
+
React.useEffect(() => {
|
|
225
|
+
const input = ref.current;
|
|
226
|
+
const inputProto = window.HTMLInputElement.prototype;
|
|
227
|
+
const descriptor = Object.getOwnPropertyDescriptor(inputProto, "value");
|
|
228
|
+
const setValue = descriptor.set;
|
|
229
|
+
if (prevValue !== value && setValue) {
|
|
230
|
+
const event = new Event("input", { bubbles: true });
|
|
231
|
+
setValue.call(input, value);
|
|
232
|
+
input.dispatchEvent(event);
|
|
233
|
+
}
|
|
234
|
+
}, [prevValue, value]);
|
|
235
|
+
return <input style={{ display: "none" }} {...inputProps} ref={ref} defaultValue={value} />;
|
|
236
|
+
}, "BubbleInput");
|
|
237
|
+
const Track = SliderTrack;
|
|
238
|
+
const Range = SliderTrackActive;
|
|
239
|
+
const Thumb = SliderThumb;
|
|
240
|
+
export {
|
|
241
|
+
Range,
|
|
242
|
+
Slider,
|
|
243
|
+
SliderThumb,
|
|
244
|
+
SliderTrack,
|
|
245
|
+
SliderTrackActive,
|
|
246
|
+
Thumb,
|
|
247
|
+
Track
|
|
248
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { composeEventHandlers, styled } from "@tamagui/core";
|
|
2
|
+
import { YStack, getCircleSize } from "@tamagui/stacks";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { SLIDER_NAME, useSliderContext } from "./context";
|
|
5
|
+
const DirectionalYStack = styled(YStack, {
|
|
6
|
+
variants: {
|
|
7
|
+
orientation: {
|
|
8
|
+
horizontal: {},
|
|
9
|
+
vertical: {}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
const SliderFrame = styled(DirectionalYStack, {
|
|
14
|
+
name: "Slider",
|
|
15
|
+
position: "relative",
|
|
16
|
+
variants: {
|
|
17
|
+
size: (val, extras) => {
|
|
18
|
+
const orientation = extras.props.orientation;
|
|
19
|
+
const circleSize = getCircleSize(val, extras);
|
|
20
|
+
const size = circleSize / 4;
|
|
21
|
+
if (orientation === "horizontal") {
|
|
22
|
+
return {
|
|
23
|
+
height: size,
|
|
24
|
+
width: 100
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
width: size,
|
|
29
|
+
height: 100
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
const SliderImpl = React.forwardRef((props, forwardedRef) => {
|
|
35
|
+
const {
|
|
36
|
+
__scopeSlider,
|
|
37
|
+
onSlideStart,
|
|
38
|
+
onSlideMove,
|
|
39
|
+
onSlideEnd,
|
|
40
|
+
onHomeKeyDown,
|
|
41
|
+
onEndKeyDown,
|
|
42
|
+
onStepKeyDown,
|
|
43
|
+
...sliderProps
|
|
44
|
+
} = props;
|
|
45
|
+
const context = useSliderContext(SLIDER_NAME, __scopeSlider);
|
|
46
|
+
return <SliderFrame size="$4" {...sliderProps} data-orientation={sliderProps.orientation} ref={forwardedRef} onStartShouldSetResponder={() => true} onResponderGrant={composeEventHandlers(props.onResponderGrant, (event) => {
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
onSlideStart(event);
|
|
49
|
+
})} onResponderMove={composeEventHandlers(props.onResponderMove, (event) => {
|
|
50
|
+
onSlideMove(event);
|
|
51
|
+
})} onResponderRelease={composeEventHandlers(props.onResponderRelease, (event) => {
|
|
52
|
+
onSlideEnd(event);
|
|
53
|
+
})} />;
|
|
54
|
+
});
|
|
55
|
+
export {
|
|
56
|
+
DirectionalYStack,
|
|
57
|
+
SliderFrame,
|
|
58
|
+
SliderImpl
|
|
59
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createContextScope } from "@tamagui/create-context";
|
|
2
|
+
const SLIDER_NAME = "Slider";
|
|
3
|
+
const [createSliderContext, createSliderScope] = createContextScope(SLIDER_NAME);
|
|
4
|
+
const [SliderProvider, useSliderContext] = createSliderContext(SLIDER_NAME);
|
|
5
|
+
const [SliderOrientationProvider, useSliderOrientationContext] = createSliderContext(SLIDER_NAME, {
|
|
6
|
+
startEdge: "left",
|
|
7
|
+
endEdge: "right",
|
|
8
|
+
sizeProp: "width",
|
|
9
|
+
size: 0,
|
|
10
|
+
direction: 1
|
|
11
|
+
});
|
|
12
|
+
export {
|
|
13
|
+
SLIDER_NAME,
|
|
14
|
+
SliderOrientationProvider,
|
|
15
|
+
SliderProvider,
|
|
16
|
+
createSliderContext,
|
|
17
|
+
createSliderScope,
|
|
18
|
+
useSliderContext,
|
|
19
|
+
useSliderOrientationContext
|
|
20
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { getTokens, getVariableValue } from "@tamagui/core";
|
|
4
|
+
function getNextSortedValues(prevValues = [], nextValue, atIndex) {
|
|
5
|
+
const nextValues = [...prevValues];
|
|
6
|
+
nextValues[atIndex] = nextValue;
|
|
7
|
+
return nextValues.sort((a, b) => a - b);
|
|
8
|
+
}
|
|
9
|
+
__name(getNextSortedValues, "getNextSortedValues");
|
|
10
|
+
function convertValueToPercentage(value, min, max) {
|
|
11
|
+
const maxSteps = max - min;
|
|
12
|
+
const percentPerStep = 100 / maxSteps;
|
|
13
|
+
return percentPerStep * (value - min);
|
|
14
|
+
}
|
|
15
|
+
__name(convertValueToPercentage, "convertValueToPercentage");
|
|
16
|
+
function getLabel(index, totalValues) {
|
|
17
|
+
if (totalValues > 2) {
|
|
18
|
+
return `Value ${index + 1} of ${totalValues}`;
|
|
19
|
+
} else if (totalValues === 2) {
|
|
20
|
+
return ["Minimum", "Maximum"][index];
|
|
21
|
+
} else {
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
__name(getLabel, "getLabel");
|
|
26
|
+
function getClosestValueIndex(values, nextValue) {
|
|
27
|
+
if (values.length === 1)
|
|
28
|
+
return 0;
|
|
29
|
+
const distances = values.map((value) => Math.abs(value - nextValue));
|
|
30
|
+
const closestDistance = Math.min(...distances);
|
|
31
|
+
return distances.indexOf(closestDistance);
|
|
32
|
+
}
|
|
33
|
+
__name(getClosestValueIndex, "getClosestValueIndex");
|
|
34
|
+
function getThumbInBoundsOffset(width, left, direction) {
|
|
35
|
+
const halfWidth = width / 2;
|
|
36
|
+
const halfPercent = 50;
|
|
37
|
+
const offset = linearScale([0, halfPercent], [0, halfWidth]);
|
|
38
|
+
return (halfWidth - offset(left) * direction) * direction;
|
|
39
|
+
}
|
|
40
|
+
__name(getThumbInBoundsOffset, "getThumbInBoundsOffset");
|
|
41
|
+
function getStepsBetweenValues(values) {
|
|
42
|
+
return values.slice(0, -1).map((value, index) => values[index + 1] - value);
|
|
43
|
+
}
|
|
44
|
+
__name(getStepsBetweenValues, "getStepsBetweenValues");
|
|
45
|
+
function hasMinStepsBetweenValues(values, minStepsBetweenValues) {
|
|
46
|
+
if (minStepsBetweenValues > 0) {
|
|
47
|
+
const stepsBetweenValues = getStepsBetweenValues(values);
|
|
48
|
+
const actualMinStepsBetweenValues = Math.min(...stepsBetweenValues);
|
|
49
|
+
return actualMinStepsBetweenValues >= minStepsBetweenValues;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
__name(hasMinStepsBetweenValues, "hasMinStepsBetweenValues");
|
|
54
|
+
function linearScale(input, output) {
|
|
55
|
+
return (value) => {
|
|
56
|
+
if (input[0] === input[1] || output[0] === output[1])
|
|
57
|
+
return output[0];
|
|
58
|
+
const ratio = (output[1] - output[0]) / (input[1] - input[0]);
|
|
59
|
+
return output[0] + ratio * (value - input[0]);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
__name(linearScale, "linearScale");
|
|
63
|
+
function getDecimalCount(value) {
|
|
64
|
+
return (String(value).split(".")[1] || "").length;
|
|
65
|
+
}
|
|
66
|
+
__name(getDecimalCount, "getDecimalCount");
|
|
67
|
+
function roundValue(value, decimalCount) {
|
|
68
|
+
const rounder = Math.pow(10, decimalCount);
|
|
69
|
+
return Math.round(value * rounder) / rounder;
|
|
70
|
+
}
|
|
71
|
+
__name(roundValue, "roundValue");
|
|
72
|
+
function getSize(size) {
|
|
73
|
+
const tokens = getTokens();
|
|
74
|
+
return typeof size === "number" ? size : size ? getVariableValue(tokens.size[size]) : null;
|
|
75
|
+
}
|
|
76
|
+
__name(getSize, "getSize");
|
|
77
|
+
export {
|
|
78
|
+
convertValueToPercentage,
|
|
79
|
+
getClosestValueIndex,
|
|
80
|
+
getDecimalCount,
|
|
81
|
+
getLabel,
|
|
82
|
+
getNextSortedValues,
|
|
83
|
+
getSize,
|
|
84
|
+
getThumbInBoundsOffset,
|
|
85
|
+
hasMinStepsBetweenValues,
|
|
86
|
+
linearScale,
|
|
87
|
+
roundValue
|
|
88
|
+
};
|
|
File without changes
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tamagui/slider",
|
|
3
|
+
"version": "1.0.1-beta.26",
|
|
4
|
+
"sideEffects": true,
|
|
5
|
+
"source": "src/index.ts",
|
|
6
|
+
"types": "./types/index.d.ts",
|
|
7
|
+
"main": "dist/cjs",
|
|
8
|
+
"module": "dist/esm",
|
|
9
|
+
"module:jsx": "dist/jsx",
|
|
10
|
+
"files": [
|
|
11
|
+
"types",
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tamagui-build",
|
|
16
|
+
"watch": "tamagui-build --watch",
|
|
17
|
+
"clean": "tamagui-build clean",
|
|
18
|
+
"clean:build": "tamagui-build clean:build"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@radix-ui/react-use-previous": "^0.1.1",
|
|
22
|
+
"@tamagui/compose-refs": "^1.0.1-beta.26",
|
|
23
|
+
"@tamagui/core": "^1.0.1-beta.26",
|
|
24
|
+
"@tamagui/create-context": "^1.0.1-beta.26",
|
|
25
|
+
"@tamagui/stacks": "^1.0.1-beta.26",
|
|
26
|
+
"@tamagui/use-controllable-state": "^1.0.1-beta.26",
|
|
27
|
+
"@tamagui/use-direction": "^1.0.1-beta.26"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"react": "*",
|
|
31
|
+
"react-dom": "*",
|
|
32
|
+
"react-native": "*"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@tamagui/build": "^1.0.1-beta.26",
|
|
36
|
+
"@types/react-native": "^0.67.3",
|
|
37
|
+
"react": "*",
|
|
38
|
+
"react-dom": "*",
|
|
39
|
+
"react-native": "*"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
}
|
|
44
|
+
}
|