PageSourceSearch

https://railsblocks.com/assets/controllers/slider_number_flow_cont…c668689012c736b45271025c17e280a90018c298.js

js railsblocks.com collected 2026-09-25 20:24:18 UTC 3,590 bytes, 90 lines download raw bytes

1import { Controller } from "@hotwired/stimulus";
2import "number-flow";
3import { continuous } from "number-flow";
4import { animate, spring } from "motion"; // Import motion for smooth thumb animation
5
6export default class extends Controller {
7  static targets = ["rangeInput", "numberFlowContainer", "track"];
8
9  static values = {
10    min: { type: Number, default: 0 }, // Minimum value
11    max: { type: Number, default: 100 }, // Maximum value
12    initial: { type: Number, default: 50 }, // Initial value
13    animationDuration: { type: Number, default: 500 }, // NumberFlow animation
14    thumbAnimationDuration: { type: Number, default: 0.5 }, // Animation duration in seconds
15  };
16
17  connect() {
18    this.numberFlowContainerTarget.innerHTML = '<number-flow class="text-lg font-semibold"></number-flow>';
19    this.flow = this.numberFlowContainerTarget.querySelector("number-flow");
20
21    this.flow.locales = "en-US";
22    this.flow.willChange = true;
23    this.flow.plugins = [continuous];
24    this.flow.format = { useGrouping: false }; // Typically no grouping for slider values
25
26    // From example, opacity and transform timings
27    this.flow.opacityTiming = {
28      duration: 250,
29      easing: "ease-out",
30    };
31    // Complex easing from example - this specific one might need adjustment if not directly translatable
32    // For simplicity, using a standard ease-out or a spring.
33    this.flow.transformTiming = {
34      easing: "ease-out", // Replaced complex linear() with ease-out
35      duration: this.animationDurationValue,
36    };
37
38    this.rangeInputTarget.min = this.minValue;
39    this.rangeInputTarget.max = this.maxValue;
40    this.rangeInputTarget.value = this.initialValue;
41    this.flow.update(this.initialValue);
42
43    // Initial positioning of the number flow container
44    this.updateNumberFlowPosition();
45  }
46
47  handleInput(event) {
48    const value = parseInt(event.currentTarget.value, 10);
49    this.flow.update(value);
50    this.updateNumberFlowPosition();
51  }
52
53  updateNumberFlowPosition() {
54    if (!this.trackTarget || !this.rangeInputTarget || !this.numberFlowContainerTarget) return;
55
56    const input = this.rangeInputTarget;
57    const container = this.numberFlowContainerTarget;
58    const track = this.trackTarget;
59
60    const min = parseFloat(input.min);
61    const max = parseFloat(input.max);
62    const val = parseFloat(input.value);
63
64    const trackRect = track.getBoundingClientRect();
65    const thumbWidth = container.offsetWidth; // Approximate thumb width by the container
66
67    // Calculate percentage position
68    const percent = (val - min) / (max - min);
69
70    // Calculate the new left position for the number flow container
71    // It should align its center with the thumb's center.
72    // The native thumb position is tricky to get, so we base it on track width and percentage.
73    let newLeft = percent * trackRect.width;
74
75    // Adjust so the numberFlowContainer is centered above the thumb position
76    // This means shifting it left by half its own width, and then potentially by half the native thumb width if known.
77    // For simplicity, we center it relative to the calculated point on the track.
78    newLeft -= thumbWidth / 2;
79
80    // Keep it within the bounds of the track visually
81    newLeft = Math.max(0, Math.min(newLeft, trackRect.width - thumbWidth));
82
83    // The `left` property needs the parent to be `position: relative` and this to be `position: absolute`.
84    animate(
85      container,
86      { left: `${newLeft}px` },
87      { duration: this.thumbAnimationDurationValue, easing: spring({ stiffness: 300, damping: 25 }) },
88    );
89  }
90};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.