@choice-ui/react 1.8.7 → 1.8.8
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/components/button/dist/index.js +7 -0
- package/dist/components/colors/src/color-image-paint/color-image-paint.js +3 -3
- package/dist/components/dropdown/dist/index.d.ts +6 -0
- package/dist/components/dropdown/dist/index.js +12 -8
- package/dist/components/emoji-picker/dist/index.d.ts +29 -1
- package/dist/components/emoji-picker/dist/index.js +144 -42
- package/dist/components/form/src/adapters/range-adapter.js +2 -2
- package/dist/components/icon-button/dist/index.d.ts +1 -1
- package/dist/components/icon-button/dist/index.js +39 -0
- package/dist/components/menus/dist/index.d.ts +5 -0
- package/dist/components/menus/dist/index.js +18 -1
- package/dist/components/range/dist/index.d.ts +276 -20
- package/dist/components/range/dist/index.js +1030 -602
- package/dist/components/range/src/components/connects.d.ts +26 -0
- package/dist/components/range/src/components/connects.js +192 -0
- package/dist/components/range/src/components/dot.d.ts +8 -0
- package/dist/components/range/src/components/dot.js +148 -0
- package/dist/components/range/src/components/thumb.d.ts +14 -0
- package/dist/components/range/src/components/thumb.js +159 -0
- package/dist/components/range/src/context/index.d.ts +4 -0
- package/dist/components/range/src/context/range-context.d.ts +35 -0
- package/dist/components/range/src/context/range-context.js +13 -0
- package/dist/components/range/src/context/range-tuple-context.d.ts +42 -0
- package/dist/components/range/src/context/range-tuple-context.js +15 -0
- package/dist/components/range/src/index.d.ts +4 -2
- package/dist/components/range/src/range-tuple.d.ts +17 -9
- package/dist/components/range/src/range-tuple.js +375 -441
- package/dist/components/range/src/range.d.ts +17 -9
- package/dist/components/range/src/range.js +164 -154
- package/dist/components/range/src/tv.d.ts +15 -3
- package/dist/components/range/src/tv.js +10 -7
- package/dist/components/textarea/dist/index.js +3 -1
- package/dist/components/tooltip/dist/index.d.ts +2 -0
- package/dist/components/tooltip/dist/index.js +23 -5
- package/dist/components/virtual-select/dist/index.d.ts +48 -0
- package/dist/index.js +6 -0
- package/package.json +20 -32
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { clamp } from "es-toolkit";
|
|
3
|
-
import { forwardRef, useState, useCallback,
|
|
3
|
+
import { forwardRef, useMemo, Children, isValidElement, useState, useCallback, useRef, useEffect } from "react";
|
|
4
4
|
import { useEventCallback } from "usehooks-ts";
|
|
5
|
+
import { RangeTupleConnects, RangeTupleContainer } from "./components/connects.js";
|
|
6
|
+
import { RangeTupleDot } from "./components/dot.js";
|
|
7
|
+
import { RangeTupleThumb } from "./components/thumb.js";
|
|
5
8
|
import { rangeTv } from "./tv.js";
|
|
9
|
+
import { RangeTupleContext } from "./context/range-tuple-context.js";
|
|
6
10
|
import { useIsomorphicLayoutEffect } from "../../../shared/hooks/use-isomorphic-layout-effect/use-isomorphic-layout-effect.js";
|
|
7
11
|
import { tcx } from "../../../shared/utils/tcx/tcx.js";
|
|
8
12
|
import { mergeRefs } from "../../../shared/utils/merge-refs/merge-refs.js";
|
|
@@ -16,281 +20,174 @@ function normalizeTuple(value, min, max) {
|
|
|
16
20
|
}
|
|
17
21
|
return [clamp(value, min, max), max];
|
|
18
22
|
}
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
return normalizedDefaultValue;
|
|
59
|
-
}, [normalizedDefaultValue, step, min]);
|
|
60
|
-
const sliderRef = useRef(null);
|
|
61
|
-
const thumb0Ref = useRef(null);
|
|
62
|
-
const thumb1Ref = useRef(null);
|
|
63
|
-
const input0Ref = useRef(null);
|
|
64
|
-
const input1Ref = useRef(null);
|
|
65
|
-
const isDragging = useRef(null);
|
|
66
|
-
const [internalValue, setInternalValue] = useState(
|
|
67
|
-
normalizeTuple(value, min, max)
|
|
68
|
-
);
|
|
69
|
-
const currentValue = useMemo(
|
|
70
|
-
() => value ? normalizeTuple(value, min, max) : internalValue,
|
|
71
|
-
[value, min, max, internalValue]
|
|
72
|
-
);
|
|
73
|
-
const currentStepValue = useMemo(() => {
|
|
74
|
-
if (step > 1) {
|
|
75
|
-
return currentValue.map((v) => Math.round(v / step) * step);
|
|
76
|
-
}
|
|
77
|
-
return currentValue;
|
|
78
|
-
}, [currentValue, step]);
|
|
79
|
-
const [transforms, setTransforms] = useState({
|
|
80
|
-
minTransform: 1,
|
|
81
|
-
maxTransform: 0,
|
|
82
|
-
transformX0: 0,
|
|
83
|
-
transformX1: 0
|
|
84
|
-
});
|
|
85
|
-
const trackWidth = useMemo(() => {
|
|
86
|
-
if ((trackSize == null ? void 0 : trackSize.width) === "auto") {
|
|
87
|
-
return actualTrackWidth;
|
|
88
|
-
}
|
|
89
|
-
return trackSize == null ? void 0 : trackSize.width;
|
|
90
|
-
}, [trackSize == null ? void 0 : trackSize.width, actualTrackWidth]);
|
|
91
|
-
useIsomorphicLayoutEffect(() => {
|
|
92
|
-
if ((trackSize == null ? void 0 : trackSize.width) === "auto" && sliderRef.current) {
|
|
93
|
-
const updateWidth = () => {
|
|
94
|
-
if (sliderRef.current) {
|
|
95
|
-
const width = sliderRef.current.getBoundingClientRect().width;
|
|
96
|
-
if (width > 0) {
|
|
97
|
-
setActualTrackWidth(width);
|
|
98
|
-
}
|
|
23
|
+
const RangeTupleRoot = forwardRef(function RangeTuple2(props, ref) {
|
|
24
|
+
const {
|
|
25
|
+
children,
|
|
26
|
+
defaultValue,
|
|
27
|
+
value,
|
|
28
|
+
onChange,
|
|
29
|
+
onChangeStart,
|
|
30
|
+
onChangeEnd,
|
|
31
|
+
min = 0,
|
|
32
|
+
max = 100,
|
|
33
|
+
step = 1,
|
|
34
|
+
disabled = false,
|
|
35
|
+
readOnly = false,
|
|
36
|
+
className,
|
|
37
|
+
width: propsWidth = 256,
|
|
38
|
+
thumbSize: propsThumbSize = 14
|
|
39
|
+
} = props;
|
|
40
|
+
const {
|
|
41
|
+
hasCustomChildren,
|
|
42
|
+
hasCustomDot,
|
|
43
|
+
hasCustomConnects,
|
|
44
|
+
extractedThumbSize,
|
|
45
|
+
extractedTrackHeight
|
|
46
|
+
} = useMemo(() => {
|
|
47
|
+
const childArray = Children.toArray(children);
|
|
48
|
+
let hasCustom = false;
|
|
49
|
+
let hasDot = false;
|
|
50
|
+
let hasConnects = false;
|
|
51
|
+
let thumbSizeFromChild;
|
|
52
|
+
let trackHeightFromChild;
|
|
53
|
+
for (const child of childArray) {
|
|
54
|
+
if (isValidElement(child)) {
|
|
55
|
+
const type = child.type;
|
|
56
|
+
if (child.type === RangeTupleThumb || (type == null ? void 0 : type.displayName) === "RangeTupleThumb") {
|
|
57
|
+
hasCustom = true;
|
|
58
|
+
const childProps = child.props;
|
|
59
|
+
if (childProps.size !== void 0) {
|
|
60
|
+
thumbSizeFromChild = childProps.size;
|
|
99
61
|
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
resizeObserver.observe(sliderRef.current);
|
|
106
|
-
return () => {
|
|
107
|
-
resizeObserver.disconnect();
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
}, [trackSize == null ? void 0 : trackSize.width]);
|
|
111
|
-
useEffect(() => {
|
|
112
|
-
const position0 = valueToPosition(currentValue[0]);
|
|
113
|
-
const position1 = valueToPosition(currentValue[1]);
|
|
114
|
-
const minTransform = 1;
|
|
115
|
-
const maxTransform = (trackWidth ?? 0) - thumbSize - 1;
|
|
116
|
-
const transformX0 = minTransform + position0 * (maxTransform - minTransform);
|
|
117
|
-
const transformX1 = minTransform + position1 * (maxTransform - minTransform);
|
|
118
|
-
setTransforms({
|
|
119
|
-
minTransform,
|
|
120
|
-
maxTransform,
|
|
121
|
-
transformX0,
|
|
122
|
-
transformX1
|
|
123
|
-
});
|
|
124
|
-
}, [currentValue, trackWidth, thumbSize, valueToPosition]);
|
|
125
|
-
const dotsData = useMemo(() => {
|
|
126
|
-
if (!step || step <= 1) return null;
|
|
127
|
-
return Array.from({ length: Math.ceil((max - min) / step) + 1 }, (_, i) => {
|
|
128
|
-
const dotValue = min + i * step;
|
|
129
|
-
const dotPosition = valueToPosition(dotValue);
|
|
130
|
-
return {
|
|
131
|
-
value: dotValue,
|
|
132
|
-
position: dotPosition
|
|
133
|
-
};
|
|
134
|
-
});
|
|
135
|
-
}, [step, min, max, valueToPosition]);
|
|
136
|
-
const defaultDotPositions = useMemo(() => {
|
|
137
|
-
if (!normalizedDefaultValue || step > 1) return null;
|
|
138
|
-
return normalizedDefaultValue.map((v) => valueToPosition(v));
|
|
139
|
-
}, [normalizedDefaultValue, step, valueToPosition]);
|
|
140
|
-
const updatePosition = useEventCallback(
|
|
141
|
-
(clientX, thumbIndex, isEnd) => {
|
|
142
|
-
var _a;
|
|
143
|
-
if (readOnly) return;
|
|
144
|
-
const rect = (_a = sliderRef.current) == null ? void 0 : _a.getBoundingClientRect();
|
|
145
|
-
if (!rect) return;
|
|
146
|
-
const newPosition = clamp((clientX - rect.left) / rect.width, 0, 1);
|
|
147
|
-
const newValue = Math.round(positionToValue(newPosition) / step) * step;
|
|
148
|
-
let clampedValue = clamp(newValue, min, max);
|
|
149
|
-
if (normalizedDefaultValue && step === 1) {
|
|
150
|
-
const snapThreshold = (max - min) * 0.05;
|
|
151
|
-
for (const defVal of normalizedDefaultValue) {
|
|
152
|
-
const distanceToDefault = Math.abs(clampedValue - defVal);
|
|
153
|
-
if (distanceToDefault <= snapThreshold) {
|
|
154
|
-
clampedValue = defVal;
|
|
155
|
-
break;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
const newTuple = [...currentValue];
|
|
160
|
-
newTuple[thumbIndex] = clampedValue;
|
|
161
|
-
if (newTuple[0] > newTuple[1]) {
|
|
162
|
-
if (thumbIndex === 0) {
|
|
163
|
-
newTuple[0] = newTuple[1];
|
|
164
|
-
} else {
|
|
165
|
-
newTuple[1] = newTuple[0];
|
|
62
|
+
} else if (child.type === RangeTupleContainer || (type == null ? void 0 : type.displayName) === "RangeTupleContainer") {
|
|
63
|
+
hasCustom = true;
|
|
64
|
+
const childProps = child.props;
|
|
65
|
+
if (childProps.height !== void 0) {
|
|
66
|
+
trackHeightFromChild = childProps.height;
|
|
166
67
|
}
|
|
68
|
+
} else if (child.type === RangeTupleConnects || (type == null ? void 0 : type.displayName) === "RangeTupleConnects") {
|
|
69
|
+
hasCustom = true;
|
|
70
|
+
hasConnects = true;
|
|
71
|
+
} else if (child.type === RangeTupleDot || (type == null ? void 0 : type.displayName) === "RangeTupleDot") {
|
|
72
|
+
hasCustom = true;
|
|
73
|
+
hasDot = true;
|
|
167
74
|
}
|
|
168
|
-
if (isEnd) {
|
|
169
|
-
isDragging.current = null;
|
|
170
|
-
}
|
|
171
|
-
if (value === void 0) {
|
|
172
|
-
setInternalValue(newTuple);
|
|
173
|
-
}
|
|
174
|
-
onChange == null ? void 0 : onChange(newTuple);
|
|
175
|
-
}
|
|
176
|
-
);
|
|
177
|
-
useEffect(() => {
|
|
178
|
-
if (value !== void 0) {
|
|
179
|
-
setInternalValue(normalizeTuple(value, min, max));
|
|
180
75
|
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
hasCustomChildren: hasCustom,
|
|
79
|
+
hasCustomDot: hasDot,
|
|
80
|
+
hasCustomConnects: hasConnects,
|
|
81
|
+
extractedThumbSize: thumbSizeFromChild,
|
|
82
|
+
extractedTrackHeight: trackHeightFromChild
|
|
83
|
+
};
|
|
84
|
+
}, [children]);
|
|
85
|
+
const thumbSize = extractedThumbSize ?? propsThumbSize;
|
|
86
|
+
const trackHeight = extractedTrackHeight ?? 16;
|
|
87
|
+
const safeStep = step > 0 ? step : 1;
|
|
88
|
+
const range = max - min || 1;
|
|
89
|
+
const [actualTrackWidth, setActualTrackWidth] = useState();
|
|
90
|
+
const valueToPosition = useCallback((val) => (val - min) / range, [min, range]);
|
|
91
|
+
const positionToValue = useCallback((position) => min + position * range, [min, range]);
|
|
92
|
+
const normalizedDefaultValue = useMemo(
|
|
93
|
+
() => defaultValue ? normalizeTuple(defaultValue, min, max) : void 0,
|
|
94
|
+
[defaultValue, min, max]
|
|
95
|
+
);
|
|
96
|
+
const defaultStepValue = useMemo(() => {
|
|
97
|
+
if (!normalizedDefaultValue) return null;
|
|
98
|
+
if (safeStep > 1) {
|
|
99
|
+
return normalizedDefaultValue.map(
|
|
100
|
+
(v) => Math.round((v - min) / safeStep) * safeStep + min
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
return normalizedDefaultValue;
|
|
104
|
+
}, [normalizedDefaultValue, safeStep, min]);
|
|
105
|
+
const sliderRef = useRef(null);
|
|
106
|
+
const thumb0Ref = useRef(null);
|
|
107
|
+
const thumb1Ref = useRef(null);
|
|
108
|
+
const input0Ref = useRef(null);
|
|
109
|
+
const input1Ref = useRef(null);
|
|
110
|
+
const isDragging = useRef(null);
|
|
111
|
+
const cleanupRef = useRef(null);
|
|
112
|
+
const [internalValue, setInternalValue] = useState(
|
|
113
|
+
normalizeTuple(value, min, max)
|
|
114
|
+
);
|
|
115
|
+
const currentValue = useMemo(
|
|
116
|
+
() => value ? normalizeTuple(value, min, max) : internalValue,
|
|
117
|
+
[value, min, max, internalValue]
|
|
118
|
+
);
|
|
119
|
+
const currentStepValue = useMemo(() => {
|
|
120
|
+
if (safeStep > 1) {
|
|
121
|
+
return currentValue.map((v) => Math.round(v / safeStep) * safeStep);
|
|
122
|
+
}
|
|
123
|
+
return currentValue;
|
|
124
|
+
}, [currentValue, safeStep]);
|
|
125
|
+
const trackWidth = typeof propsWidth === "number" ? propsWidth : actualTrackWidth;
|
|
126
|
+
useIsomorphicLayoutEffect(() => {
|
|
127
|
+
if (typeof propsWidth !== "number" && sliderRef.current) {
|
|
128
|
+
const updateWidth = () => {
|
|
129
|
+
if (sliderRef.current) {
|
|
130
|
+
const width = sliderRef.current.getBoundingClientRect().width;
|
|
131
|
+
if (width > 0) {
|
|
132
|
+
setActualTrackWidth(width);
|
|
207
133
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
updateWidth();
|
|
137
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
138
|
+
updateWidth();
|
|
139
|
+
});
|
|
140
|
+
resizeObserver.observe(sliderRef.current);
|
|
141
|
+
return () => {
|
|
142
|
+
resizeObserver.disconnect();
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}, [propsWidth]);
|
|
146
|
+
const transforms = useMemo(() => {
|
|
147
|
+
const position0 = valueToPosition(currentValue[0]);
|
|
148
|
+
const position1 = valueToPosition(currentValue[1]);
|
|
149
|
+
const minTransform = 1;
|
|
150
|
+
const maxTransform = (trackWidth ?? 0) - thumbSize - 1;
|
|
151
|
+
const transformX0 = minTransform + position0 * (maxTransform - minTransform);
|
|
152
|
+
const transformX1 = minTransform + position1 * (maxTransform - minTransform);
|
|
153
|
+
return { minTransform, maxTransform, transformX0, transformX1 };
|
|
154
|
+
}, [currentValue, trackWidth, thumbSize, valueToPosition]);
|
|
155
|
+
const dotsData = useMemo(() => {
|
|
156
|
+
if (safeStep <= 1) return null;
|
|
157
|
+
return Array.from({ length: Math.ceil((max - min) / safeStep) + 1 }, (_, i) => {
|
|
158
|
+
const dotValue = min + i * safeStep;
|
|
159
|
+
const dotPosition = valueToPosition(dotValue);
|
|
160
|
+
return {
|
|
161
|
+
value: dotValue,
|
|
162
|
+
position: dotPosition
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
}, [safeStep, min, max, valueToPosition]);
|
|
166
|
+
const defaultDotPositions = useMemo(() => {
|
|
167
|
+
if (!normalizedDefaultValue || safeStep > 1) return null;
|
|
168
|
+
return normalizedDefaultValue.map((v) => valueToPosition(v));
|
|
169
|
+
}, [normalizedDefaultValue, safeStep, valueToPosition]);
|
|
170
|
+
const updatePosition = useEventCallback(
|
|
171
|
+
(clientX, thumbIndex, isEnd) => {
|
|
172
|
+
var _a;
|
|
173
|
+
if (readOnly) return;
|
|
174
|
+
const rect = (_a = sliderRef.current) == null ? void 0 : _a.getBoundingClientRect();
|
|
175
|
+
if (!rect) return;
|
|
176
|
+
const newPosition = clamp((clientX - rect.left) / rect.width, 0, 1);
|
|
177
|
+
const newValue = Math.round(positionToValue(newPosition) / safeStep) * safeStep;
|
|
178
|
+
let clampedValue = clamp(newValue, min, max);
|
|
179
|
+
if (normalizedDefaultValue && safeStep <= 1) {
|
|
180
|
+
const snapThreshold = (max - min) * 0.05;
|
|
181
|
+
for (const defVal of normalizedDefaultValue) {
|
|
182
|
+
const distanceToDefault = Math.abs(clampedValue - defVal);
|
|
183
|
+
if (distanceToDefault <= snapThreshold) {
|
|
184
|
+
clampedValue = defVal;
|
|
185
|
+
break;
|
|
235
186
|
}
|
|
236
|
-
|
|
237
|
-
window.removeEventListener("pointerup", handleUp);
|
|
238
|
-
window.removeEventListener("pointercancel", handleUp);
|
|
239
|
-
};
|
|
240
|
-
window.addEventListener("pointermove", handleMove);
|
|
241
|
-
window.addEventListener("pointerup", handleUp);
|
|
242
|
-
window.addEventListener("pointercancel", handleUp);
|
|
243
|
-
},
|
|
244
|
-
[
|
|
245
|
-
disabled,
|
|
246
|
-
readOnly,
|
|
247
|
-
onChangeEnd,
|
|
248
|
-
onChangeStart,
|
|
249
|
-
updatePosition,
|
|
250
|
-
positionToValue,
|
|
251
|
-
step,
|
|
252
|
-
min,
|
|
253
|
-
max,
|
|
254
|
-
normalizedDefaultValue,
|
|
255
|
-
currentValue
|
|
256
|
-
]
|
|
257
|
-
);
|
|
258
|
-
const handleSliderPointerDown = useCallback(
|
|
259
|
-
(e) => {
|
|
260
|
-
var _a;
|
|
261
|
-
if (disabled || readOnly) return;
|
|
262
|
-
if (e.target === thumb0Ref.current || e.target === thumb1Ref.current) return;
|
|
263
|
-
const rect = (_a = sliderRef.current) == null ? void 0 : _a.getBoundingClientRect();
|
|
264
|
-
if (!rect) return;
|
|
265
|
-
const clickPosition = (e.clientX - rect.left) / rect.width;
|
|
266
|
-
const clickValue = positionToValue(clickPosition);
|
|
267
|
-
const dist0 = Math.abs(clickValue - currentValue[0]);
|
|
268
|
-
const dist1 = Math.abs(clickValue - currentValue[1]);
|
|
269
|
-
const thumbIndex = dist0 <= dist1 ? 0 : 1;
|
|
270
|
-
handlePointerDown(e, thumbIndex);
|
|
271
|
-
},
|
|
272
|
-
[disabled, readOnly, handlePointerDown, currentValue, positionToValue]
|
|
273
|
-
);
|
|
274
|
-
const handleKeyDown = useEventCallback((e, thumbIndex) => {
|
|
275
|
-
if (disabled || readOnly) return;
|
|
276
|
-
const stepValue = e.shiftKey ? step * 10 : step;
|
|
277
|
-
let newValue = currentValue[thumbIndex];
|
|
278
|
-
switch (e.key) {
|
|
279
|
-
case "ArrowLeft":
|
|
280
|
-
case "ArrowDown":
|
|
281
|
-
e.preventDefault();
|
|
282
|
-
newValue = clamp(newValue - stepValue, min, max);
|
|
283
|
-
break;
|
|
284
|
-
case "ArrowRight":
|
|
285
|
-
case "ArrowUp":
|
|
286
|
-
e.preventDefault();
|
|
287
|
-
newValue = clamp(newValue + stepValue, min, max);
|
|
288
|
-
break;
|
|
289
|
-
default:
|
|
290
|
-
return;
|
|
187
|
+
}
|
|
291
188
|
}
|
|
292
189
|
const newTuple = [...currentValue];
|
|
293
|
-
newTuple[thumbIndex] =
|
|
190
|
+
newTuple[thumbIndex] = clampedValue;
|
|
294
191
|
if (newTuple[0] > newTuple[1]) {
|
|
295
192
|
if (thumbIndex === 0) {
|
|
296
193
|
newTuple[0] = newTuple[1];
|
|
@@ -298,184 +195,221 @@ const RangeTuple = forwardRef(
|
|
|
298
195
|
newTuple[1] = newTuple[0];
|
|
299
196
|
}
|
|
300
197
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
useEffect(() => {
|
|
304
|
-
var _a, _b;
|
|
305
|
-
if (disabled) {
|
|
306
|
-
if (document.activeElement === input0Ref.current) {
|
|
307
|
-
(_a = input0Ref.current) == null ? void 0 : _a.blur();
|
|
308
|
-
}
|
|
309
|
-
if (document.activeElement === input1Ref.current) {
|
|
310
|
-
(_b = input1Ref.current) == null ? void 0 : _b.blur();
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}, [disabled]);
|
|
314
|
-
const tv = useMemo(
|
|
315
|
-
() => rangeTv({
|
|
316
|
-
hasStepOrDefault: step > 1 || normalizedDefaultValue !== void 0,
|
|
317
|
-
disabled
|
|
318
|
-
}),
|
|
319
|
-
[step, normalizedDefaultValue, disabled]
|
|
320
|
-
);
|
|
321
|
-
const connectsClass = useMemo(() => {
|
|
322
|
-
if (disabled) return "bg-disabled-background";
|
|
323
|
-
return connectsClassName.positive;
|
|
324
|
-
}, [disabled, connectsClassName]);
|
|
325
|
-
const connectStyle = useMemo(() => {
|
|
326
|
-
return {
|
|
327
|
-
left: `${transforms.transformX0 + thumbSize / 2}px`,
|
|
328
|
-
right: `calc(100% - ${transforms.transformX1 + thumbSize / 2}px)`,
|
|
329
|
-
height: trackSize == null ? void 0 : trackSize.height
|
|
330
|
-
};
|
|
331
|
-
}, [transforms.transformX0, transforms.transformX1, thumbSize, trackSize == null ? void 0 : trackSize.height]);
|
|
332
|
-
const renderDots = useCallback(() => {
|
|
333
|
-
if (dotsData) {
|
|
334
|
-
return dotsData.map(({ value: dotValue, position: dotPosition }) => {
|
|
335
|
-
const { minTransform, maxTransform } = transforms;
|
|
336
|
-
const dotTransform = minTransform + dotPosition * (maxTransform - minTransform);
|
|
337
|
-
const isWithinRange = dotValue >= currentValue[0] && dotValue <= currentValue[1];
|
|
338
|
-
const isDefaultValue = defaultStepValue == null ? void 0 : defaultStepValue.includes(dotValue);
|
|
339
|
-
const { dot } = rangeTv({
|
|
340
|
-
defaultStepValue: isDefaultValue,
|
|
341
|
-
overStepValue: isWithinRange
|
|
342
|
-
});
|
|
343
|
-
return /* @__PURE__ */ jsx(
|
|
344
|
-
"div",
|
|
345
|
-
{
|
|
346
|
-
className: dot(),
|
|
347
|
-
style: {
|
|
348
|
-
left: dotTransform + thumbSize / 2
|
|
349
|
-
}
|
|
350
|
-
},
|
|
351
|
-
dotValue
|
|
352
|
-
);
|
|
353
|
-
});
|
|
198
|
+
if (isEnd) {
|
|
199
|
+
isDragging.current = null;
|
|
354
200
|
}
|
|
355
|
-
if (
|
|
356
|
-
|
|
357
|
-
"div",
|
|
358
|
-
{
|
|
359
|
-
className: rangeTv({ defaultStepValue: true }).dot(),
|
|
360
|
-
style: {
|
|
361
|
-
left: transforms.minTransform + position * (transforms.maxTransform - transforms.minTransform) + thumbSize / 2
|
|
362
|
-
}
|
|
363
|
-
},
|
|
364
|
-
`default-${idx}`
|
|
365
|
-
));
|
|
201
|
+
if (value === void 0) {
|
|
202
|
+
setInternalValue(newTuple);
|
|
366
203
|
}
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
|
|
204
|
+
onChange == null ? void 0 : onChange(newTuple);
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
useEffect(() => {
|
|
208
|
+
if (value !== void 0) {
|
|
209
|
+
setInternalValue(normalizeTuple(value, min, max));
|
|
210
|
+
}
|
|
211
|
+
}, [value, min, max]);
|
|
212
|
+
const latestValueRef = useRef(currentValue);
|
|
213
|
+
latestValueRef.current = currentValue;
|
|
214
|
+
const handlePointerDown = useCallback(
|
|
215
|
+
(e, thumbIndex) => {
|
|
216
|
+
var _a;
|
|
217
|
+
if (disabled || readOnly) return;
|
|
218
|
+
e.preventDefault();
|
|
219
|
+
e.stopPropagation();
|
|
220
|
+
const thumb = thumbIndex === 0 ? thumb0Ref.current : thumb1Ref.current;
|
|
221
|
+
const inputRef = thumbIndex === 0 ? input0Ref : input1Ref;
|
|
222
|
+
if (!thumb) return;
|
|
223
|
+
onChangeStart == null ? void 0 : onChangeStart();
|
|
224
|
+
isDragging.current = thumbIndex;
|
|
225
|
+
thumb.setPointerCapture(e.pointerId);
|
|
226
|
+
updatePosition(e.clientX, thumbIndex);
|
|
227
|
+
(_a = inputRef.current) == null ? void 0 : _a.focus();
|
|
228
|
+
const handleMove = (e2) => {
|
|
229
|
+
if (isDragging.current !== thumbIndex) return;
|
|
230
|
+
e2.preventDefault();
|
|
231
|
+
updatePosition(e2.clientX, thumbIndex);
|
|
371
232
|
};
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
233
|
+
const cleanup = () => {
|
|
234
|
+
window.removeEventListener("pointermove", handleMove);
|
|
235
|
+
window.removeEventListener("pointerup", handleUp);
|
|
236
|
+
window.removeEventListener("pointercancel", handleUp);
|
|
237
|
+
cleanupRef.current = null;
|
|
238
|
+
};
|
|
239
|
+
const handleUp = (e2) => {
|
|
240
|
+
if (isDragging.current !== thumbIndex) return;
|
|
241
|
+
e2.preventDefault();
|
|
242
|
+
if (thumb.hasPointerCapture(e2.pointerId)) {
|
|
243
|
+
thumb.releasePointerCapture(e2.pointerId);
|
|
377
244
|
}
|
|
245
|
+
updatePosition(e2.clientX, thumbIndex, true);
|
|
246
|
+
isDragging.current = null;
|
|
247
|
+
onChangeEnd == null ? void 0 : onChangeEnd(latestValueRef.current);
|
|
248
|
+
cleanup();
|
|
378
249
|
};
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
},
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
()
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
()
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
willChange: isDragging.current === 0 ? "transform" : "auto"
|
|
434
|
-
},
|
|
435
|
-
children: /* @__PURE__ */ jsx(
|
|
436
|
-
"input",
|
|
437
|
-
{
|
|
438
|
-
ref: input0Ref,
|
|
439
|
-
type: "text",
|
|
440
|
-
onKeyDown: (e) => handleKeyDown(e, 0),
|
|
441
|
-
className: tv.input(),
|
|
442
|
-
tabIndex: disabled || readOnly ? -1 : 0,
|
|
443
|
-
readOnly: true
|
|
444
|
-
}
|
|
445
|
-
)
|
|
446
|
-
}
|
|
447
|
-
),
|
|
448
|
-
/* @__PURE__ */ jsx(
|
|
449
|
-
"div",
|
|
450
|
-
{
|
|
451
|
-
ref: thumb1Ref,
|
|
452
|
-
onPointerDown: (e) => handlePointerDown(e, 1),
|
|
453
|
-
className: thumbTv1.thumb(),
|
|
454
|
-
style: {
|
|
455
|
-
width: thumbSize,
|
|
456
|
-
height: thumbSize,
|
|
457
|
-
transform: `translate(${transforms.transformX1}px, -50%)`,
|
|
458
|
-
willChange: isDragging.current === 1 ? "transform" : "auto"
|
|
459
|
-
},
|
|
460
|
-
children: /* @__PURE__ */ jsx(
|
|
461
|
-
"input",
|
|
462
|
-
{
|
|
463
|
-
ref: input1Ref,
|
|
464
|
-
type: "text",
|
|
465
|
-
onKeyDown: (e) => handleKeyDown(e, 1),
|
|
466
|
-
className: tv.input(),
|
|
467
|
-
tabIndex: disabled || readOnly ? -1 : 0,
|
|
468
|
-
readOnly: true
|
|
469
|
-
}
|
|
470
|
-
)
|
|
471
|
-
}
|
|
472
|
-
)
|
|
473
|
-
]
|
|
250
|
+
cleanupRef.current = cleanup;
|
|
251
|
+
window.addEventListener("pointermove", handleMove);
|
|
252
|
+
window.addEventListener("pointerup", handleUp);
|
|
253
|
+
window.addEventListener("pointercancel", handleUp);
|
|
254
|
+
},
|
|
255
|
+
[disabled, readOnly, onChangeEnd, onChangeStart, updatePosition]
|
|
256
|
+
);
|
|
257
|
+
useEffect(() => {
|
|
258
|
+
return () => {
|
|
259
|
+
var _a;
|
|
260
|
+
(_a = cleanupRef.current) == null ? void 0 : _a.call(cleanupRef);
|
|
261
|
+
};
|
|
262
|
+
}, []);
|
|
263
|
+
const handleSliderPointerDown = useCallback(
|
|
264
|
+
(e) => {
|
|
265
|
+
var _a;
|
|
266
|
+
if (disabled || readOnly) return;
|
|
267
|
+
if (e.target === thumb0Ref.current || e.target === thumb1Ref.current) return;
|
|
268
|
+
const rect = (_a = sliderRef.current) == null ? void 0 : _a.getBoundingClientRect();
|
|
269
|
+
if (!rect) return;
|
|
270
|
+
const clickPosition = (e.clientX - rect.left) / rect.width;
|
|
271
|
+
const clickValue = positionToValue(clickPosition);
|
|
272
|
+
const dist0 = Math.abs(clickValue - currentValue[0]);
|
|
273
|
+
const dist1 = Math.abs(clickValue - currentValue[1]);
|
|
274
|
+
const thumbIndex = dist0 <= dist1 ? 0 : 1;
|
|
275
|
+
handlePointerDown(e, thumbIndex);
|
|
276
|
+
},
|
|
277
|
+
[disabled, readOnly, handlePointerDown, currentValue, positionToValue]
|
|
278
|
+
);
|
|
279
|
+
const handleKeyDown = useEventCallback((e, thumbIndex) => {
|
|
280
|
+
if (disabled || readOnly) return;
|
|
281
|
+
const stepValue = e.shiftKey ? safeStep * 10 : safeStep;
|
|
282
|
+
let newValue = currentValue[thumbIndex];
|
|
283
|
+
switch (e.key) {
|
|
284
|
+
case "ArrowLeft":
|
|
285
|
+
case "ArrowDown":
|
|
286
|
+
e.preventDefault();
|
|
287
|
+
newValue = clamp(newValue - stepValue, min, max);
|
|
288
|
+
break;
|
|
289
|
+
case "ArrowRight":
|
|
290
|
+
case "ArrowUp":
|
|
291
|
+
e.preventDefault();
|
|
292
|
+
newValue = clamp(newValue + stepValue, min, max);
|
|
293
|
+
break;
|
|
294
|
+
default:
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
const newTuple = [...currentValue];
|
|
298
|
+
newTuple[thumbIndex] = newValue;
|
|
299
|
+
if (newTuple[0] > newTuple[1]) {
|
|
300
|
+
if (thumbIndex === 0) {
|
|
301
|
+
newTuple[0] = newTuple[1];
|
|
302
|
+
} else {
|
|
303
|
+
newTuple[1] = newTuple[0];
|
|
474
304
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
);
|
|
478
|
-
|
|
305
|
+
}
|
|
306
|
+
onChange == null ? void 0 : onChange(newTuple);
|
|
307
|
+
});
|
|
308
|
+
useEffect(() => {
|
|
309
|
+
var _a, _b;
|
|
310
|
+
if (disabled) {
|
|
311
|
+
if (document.activeElement === input0Ref.current) {
|
|
312
|
+
(_a = input0Ref.current) == null ? void 0 : _a.blur();
|
|
313
|
+
}
|
|
314
|
+
if (document.activeElement === input1Ref.current) {
|
|
315
|
+
(_b = input1Ref.current) == null ? void 0 : _b.blur();
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}, [disabled]);
|
|
319
|
+
const hasStepOrDefault = safeStep > 1 || normalizedDefaultValue !== void 0;
|
|
320
|
+
const tv = useMemo(() => rangeTv({ hasStepOrDefault, disabled }), [hasStepOrDefault, disabled]);
|
|
321
|
+
const thumb0IsDefault = defaultStepValue ? currentStepValue[0] === defaultStepValue[0] : false;
|
|
322
|
+
const thumb1IsDefault = defaultStepValue ? currentStepValue[1] === defaultStepValue[1] : false;
|
|
323
|
+
const thumbTv0 = useMemo(
|
|
324
|
+
() => rangeTv({ currentDefaultValue: thumb0IsDefault, hasStepOrDefault, disabled }),
|
|
325
|
+
[thumb0IsDefault, hasStepOrDefault, disabled]
|
|
326
|
+
);
|
|
327
|
+
const thumbTv1 = useMemo(
|
|
328
|
+
() => rangeTv({ currentDefaultValue: thumb1IsDefault, hasStepOrDefault, disabled }),
|
|
329
|
+
[thumb1IsDefault, hasStepOrDefault, disabled]
|
|
330
|
+
);
|
|
331
|
+
const contextValue = useMemo(
|
|
332
|
+
() => ({
|
|
333
|
+
currentValue,
|
|
334
|
+
disabled,
|
|
335
|
+
readOnly,
|
|
336
|
+
min,
|
|
337
|
+
max,
|
|
338
|
+
step: safeStep,
|
|
339
|
+
thumbSize,
|
|
340
|
+
trackHeight,
|
|
341
|
+
transforms,
|
|
342
|
+
defaultStepValue,
|
|
343
|
+
currentStepValue,
|
|
344
|
+
dotsData,
|
|
345
|
+
defaultDotPositions,
|
|
346
|
+
normalizedDefaultValue,
|
|
347
|
+
thumb0Ref,
|
|
348
|
+
thumb1Ref,
|
|
349
|
+
input0Ref,
|
|
350
|
+
input1Ref,
|
|
351
|
+
isDragging,
|
|
352
|
+
handlePointerDown,
|
|
353
|
+
handleKeyDown,
|
|
354
|
+
tv,
|
|
355
|
+
thumbTv0,
|
|
356
|
+
thumbTv1,
|
|
357
|
+
hasCustomDot,
|
|
358
|
+
hasCustomConnects,
|
|
359
|
+
isDefaultValue: thumb0IsDefault && thumb1IsDefault
|
|
360
|
+
}),
|
|
361
|
+
[
|
|
362
|
+
currentValue,
|
|
363
|
+
disabled,
|
|
364
|
+
readOnly,
|
|
365
|
+
min,
|
|
366
|
+
max,
|
|
367
|
+
safeStep,
|
|
368
|
+
thumbSize,
|
|
369
|
+
trackHeight,
|
|
370
|
+
transforms,
|
|
371
|
+
defaultStepValue,
|
|
372
|
+
currentStepValue,
|
|
373
|
+
dotsData,
|
|
374
|
+
defaultDotPositions,
|
|
375
|
+
normalizedDefaultValue,
|
|
376
|
+
handlePointerDown,
|
|
377
|
+
handleKeyDown,
|
|
378
|
+
tv,
|
|
379
|
+
thumbTv0,
|
|
380
|
+
thumbTv1,
|
|
381
|
+
hasCustomDot,
|
|
382
|
+
hasCustomConnects,
|
|
383
|
+
thumb0IsDefault,
|
|
384
|
+
thumb1IsDefault
|
|
385
|
+
]
|
|
386
|
+
);
|
|
387
|
+
return /* @__PURE__ */ jsx(RangeTupleContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
388
|
+
"div",
|
|
389
|
+
{
|
|
390
|
+
ref: mergeRefs(sliderRef, ref),
|
|
391
|
+
onPointerDown: handleSliderPointerDown,
|
|
392
|
+
className: tcx(tv.container(), className),
|
|
393
|
+
style: {
|
|
394
|
+
"--width": `${trackWidth}px`,
|
|
395
|
+
"--height": `${trackHeight}px`,
|
|
396
|
+
"--thumb-size": `${thumbSize}px`
|
|
397
|
+
},
|
|
398
|
+
children: hasCustomChildren ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
399
|
+
/* @__PURE__ */ jsx(RangeTupleContainer, {}),
|
|
400
|
+
/* @__PURE__ */ jsx(RangeTupleThumb, { index: 0 }),
|
|
401
|
+
/* @__PURE__ */ jsx(RangeTupleThumb, { index: 1 })
|
|
402
|
+
] })
|
|
403
|
+
}
|
|
404
|
+
) });
|
|
405
|
+
});
|
|
406
|
+
RangeTupleRoot.displayName = "RangeTuple";
|
|
407
|
+
const RangeTuple = Object.assign(RangeTupleRoot, {
|
|
408
|
+
Container: RangeTupleContainer,
|
|
409
|
+
Connects: RangeTupleConnects,
|
|
410
|
+
Thumb: RangeTupleThumb,
|
|
411
|
+
Dot: RangeTupleDot
|
|
412
|
+
});
|
|
479
413
|
export {
|
|
480
414
|
RangeTuple
|
|
481
415
|
};
|