bits-ui 1.3.15 → 1.3.16

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.
@@ -18,6 +18,8 @@ declare class SliderBaseRootState {
18
18
  direction: "rl" | "lr" | "tb" | "bt";
19
19
  constructor(opts: SliderBaseRootStateProps);
20
20
  getAllThumbs: () => HTMLElement[];
21
+ getThumbScale: () => [number, number];
22
+ getPositionFromValue: (thumbValue: number) => number;
21
23
  props: {
22
24
  readonly id: string;
23
25
  readonly "data-orientation": "horizontal" | "vertical";
@@ -46,7 +48,6 @@ declare class SliderSingleRootState extends SliderBaseRootState {
46
48
  handlePointerMove: (e: PointerEvent) => void;
47
49
  handlePointerDown: (e: PointerEvent) => void;
48
50
  handlePointerUp: () => void;
49
- getPositionFromValue: (thumbValue: number) => number;
50
51
  thumbsPropsArr: {
51
52
  readonly role: "slider";
52
53
  readonly "aria-valuemin": number;
@@ -98,7 +99,6 @@ declare class SliderMultiRootState extends SliderBaseRootState {
98
99
  handlePointerMove: (e: PointerEvent) => void;
99
100
  handlePointerDown: (e: PointerEvent) => void;
100
101
  handlePointerUp: () => void;
101
- getPositionFromValue: (thumbValue: number) => number;
102
102
  getAllThumbs: () => HTMLElement[];
103
103
  updateValue: (thumbValue: number, idx: number) => void;
104
104
  thumbsPropsArr: {
@@ -11,7 +11,7 @@ import { getAriaDisabled, getAriaOrientation, getDataDisabled, getDataOrientatio
11
11
  import { kbd } from "../../internal/kbd.js";
12
12
  import { isElementOrSVGElement } from "../../internal/is.js";
13
13
  import { isValidIndex } from "../../internal/arrays.js";
14
- import { snapValueToStep } from "../../internal/math.js";
14
+ import { linearScale, snapValueToStep } from "../../internal/math.js";
15
15
  const SLIDER_ROOT_ATTR = "data-slider-root";
16
16
  const SLIDER_THUMB_ATTR = "data-slider-thumb";
17
17
  const SLIDER_RANGE_ATTR = "data-slider-range";
@@ -42,6 +42,32 @@ class SliderBaseRootState {
42
42
  return [];
43
43
  return Array.from(node.querySelectorAll(`[${SLIDER_THUMB_ATTR}]`));
44
44
  };
45
+ getThumbScale = () => {
46
+ const isVertical = this.opts.orientation.current === "vertical";
47
+ // this assumes all thumbs are the same width
48
+ const activeThumb = this.getAllThumbs()[0];
49
+ const thumbSize = isVertical ? activeThumb?.offsetHeight : activeThumb?.offsetWidth;
50
+ // if thumb size is undefined or 0, fallback to a 0-100 scale
51
+ if (thumbSize === undefined || Number.isNaN(thumbSize) || thumbSize === 0)
52
+ return [0, 100];
53
+ const trackSize = isVertical
54
+ ? this.opts.ref.current?.offsetHeight
55
+ : this.opts.ref.current?.offsetWidth;
56
+ // if track size is undefined or 0, fallback to a 0-100 scale
57
+ if (trackSize === undefined || Number.isNaN(trackSize) || trackSize === 0)
58
+ return [0, 100];
59
+ // the padding on either side
60
+ // half the width of the thumb
61
+ const percentPadding = (thumbSize / 2 / trackSize) * 100;
62
+ const min = percentPadding;
63
+ const max = 100 - percentPadding;
64
+ return [min, max];
65
+ };
66
+ getPositionFromValue = (thumbValue) => {
67
+ const thumbScale = this.getThumbScale();
68
+ const scale = linearScale([this.opts.min.current, this.opts.max.current], thumbScale);
69
+ return scale(thumbValue);
70
+ };
45
71
  props = $derived.by(() => ({
46
72
  id: this.opts.id.current,
47
73
  "data-orientation": getDataOrientation(this.opts.orientation.current),
@@ -169,16 +195,11 @@ class SliderSingleRootState extends SliderBaseRootState {
169
195
  }
170
196
  this.isActive = false;
171
197
  };
172
- getPositionFromValue = (thumbValue) => {
173
- const min = this.opts.min.current;
174
- const max = this.opts.max.current;
175
- return ((thumbValue - min) / (max - min)) * 100;
176
- };
177
198
  thumbsPropsArr = $derived.by(() => {
178
199
  const currValue = this.opts.value.current;
179
200
  return Array.from({ length: 1 }, () => {
180
201
  const thumbValue = currValue;
181
- const thumbPosition = this.getPositionFromValue(thumbValue ?? 0);
202
+ const thumbPosition = this.getPositionFromValue(thumbValue);
182
203
  const style = getThumbStyles(this.direction, thumbPosition);
183
204
  return {
184
205
  role: "slider",
@@ -209,10 +230,11 @@ class SliderSingleRootState extends SliderBaseRootState {
209
230
  const currValue = this.opts.value.current;
210
231
  return Array.from({ length: count }, (_, i) => {
211
232
  const tickPosition = i * (step / difference) * 100;
233
+ const scale = linearScale([this.opts.min.current, this.opts.max.current], this.getThumbScale());
212
234
  const isFirst = i === 0;
213
235
  const isLast = i === count - 1;
214
236
  const offsetPercentage = isFirst ? 0 : isLast ? -100 : -50;
215
- const style = getTickStyles(this.direction, tickPosition, offsetPercentage);
237
+ const style = getTickStyles(this.direction, scale(tickPosition), offsetPercentage);
216
238
  const tickValue = min + i * step;
217
239
  const bounded = tickValue <= currValue;
218
240
  return {
@@ -379,11 +401,6 @@ class SliderMultiRootState extends SliderBaseRootState {
379
401
  }
380
402
  this.isActive = false;
381
403
  };
382
- getPositionFromValue = (thumbValue) => {
383
- const min = this.opts.min.current;
384
- const max = this.opts.max.current;
385
- return ((thumbValue - min) / (max - min)) * 100;
386
- };
387
404
  getAllThumbs = () => {
388
405
  const node = this.opts.ref.current;
389
406
  if (!node)
@@ -2,3 +2,4 @@
2
2
  * From https://github.com/melt-ui/melt-ui/blob/main/packages/svelte/src/lib/internal/math.ts
3
3
  */
4
4
  export declare function snapValueToStep(value: number, min: number, max: number, step: number): number;
5
+ export declare function linearScale(domain: [number, number], range: [number, number], clamp?: boolean): (x: number) => number;
@@ -26,3 +26,18 @@ export function snapValueToStep(value, min, max, step) {
26
26
  }
27
27
  return snappedValue;
28
28
  }
29
+ export function linearScale(domain, range, clamp = true) {
30
+ const [d0, d1] = domain;
31
+ const [r0, r1] = range;
32
+ const slope = (r1 - r0) / (d1 - d0);
33
+ return (x) => {
34
+ const result = r0 + slope * (x - d0);
35
+ if (!clamp)
36
+ return result;
37
+ if (result > Math.max(r0, r1))
38
+ return Math.max(r0, r1);
39
+ if (result < Math.min(r0, r1))
40
+ return Math.min(r0, r1);
41
+ return result;
42
+ };
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bits-ui",
3
- "version": "1.3.15",
3
+ "version": "1.3.16",
4
4
  "license": "MIT",
5
5
  "repository": "github:huntabyte/bits-ui",
6
6
  "funding": "https://github.com/sponsors/huntabyte",