PageSourceSearch

https://railsblocks.com/assets/controllers/activity_stats_controll…92e089bb47096da3a1babd59b7a0bd53c0011a39.js

js railsblocks.com collected 2026-09-25 20:22:32 UTC 3,692 bytes, 92 lines download raw bytes

1import { Controller } from "@hotwired/stimulus";
2import "number-flow";
3import { continuous } from "number-flow";
4
5export default class extends Controller {
6  static targets = [
7    "viewsCount",
8    "repostsCount",
9    "repostButton",
10    "repostIcon",
11    "likesCount",
12    "likeButton",
13    "likeIcon",
14    "bookmarksCount",
15    "bookmarkButton",
16    "bookmarkIcon",
17  ];
18
19  static values = {
20    initialViews: { type: Number, default: 12345 }, // Initial views count
21    initialReposts: { type: Number, default: 678 }, // Initial reposts count
22    initialLikes: { type: Number, default: 2345 }, // Initial likes count
23    initialBookmarks: { type: Number, default: 123 }, // Initial bookmarks count
24    tickAnimationDuration: { type: Number, default: 500 }, // Duration of the tick animation
25  };
26
27  connect() {
28    this.initializeNumberFlow(this.viewsCountTarget, this.initialViewsValue);
29    this.initializeNumberFlow(this.repostsCountTarget, this.initialRepostsValue);
30    this.initializeNumberFlow(this.likesCountTarget, this.initialLikesValue);
31    this.initializeNumberFlow(this.bookmarksCountTarget, this.initialBookmarksValue);
32
33    // Store toggle states
34    this.repostsActive = false;
35    this.likesActive = false;
36    this.bookmarksActive = false;
37
38    // Simulate view count increasing over time
39    this.viewsInterval = setInterval(() => {
40      const currentViews = this.viewsCountTarget.flow.value; // Read current value
41      const increment = Math.floor(Math.random() * 10) + 1;
42      this.viewsCountTarget.flow.update(currentViews + increment);
43    }, 3000);
44  }
45
46  disconnect() {
47    if (this.viewsInterval) clearInterval(this.viewsInterval);
48  }
49
50  initializeNumberFlow(targetElement, initialValue) {
51    targetElement.innerHTML = "<number-flow data-will-change></number-flow>";
52    const flowInstance = targetElement.querySelector("number-flow");
53    targetElement.flow = flowInstance; // Attach for easy access
54
55    flowInstance.format = {
56      notation: "compact",
57      compactDisplay: "short",
58      roundingMode: "trunc",
59    };
60    flowInstance.plugins = [continuous];
61    flowInstance.spinTiming = { duration: this.tickAnimationDurationValue, easing: "ease-out" };
62    flowInstance.transformTiming = { duration: this.tickAnimationDurationValue, easing: "ease-out" };
63    flowInstance.update(initialValue);
64  }
65
66  toggleReposts() {
67    this.repostsActive = !this.repostsActive;
68    const currentValue = this.repostsCountTarget.flow.value;
69    const newValue = this.repostsActive ? currentValue + 1 : currentValue - 1;
70    this.repostsCountTarget.flow.update(newValue);
71    this.repostButtonTarget.classList.toggle("text-emerald-500", this.repostsActive);
72    // this.repostIconTarget.classList.toggle('fill-current', this.repostsActive); // If you want to fill the icon
73  }
74
75  toggleLikes() {
76    this.likesActive = !this.likesActive;
77    const currentValue = this.likesCountTarget.flow.value;
78    const newValue = this.likesActive ? currentValue + 1 : currentValue - 1;
79    this.likesCountTarget.flow.update(newValue);
80    this.likeButtonTarget.classList.toggle("text-pink-500", this.likesActive);
81    this.likeIconTarget.classList.toggle("fill-pink-500", this.likesActive); // Example of filling the icon
82  }
83
84  toggleBookmarks() {
85    this.bookmarksActive = !this.bookmarksActive;
86    const currentValue = this.bookmarksCountTarget.flow.value;
87    const newValue = this.bookmarksActive ? currentValue + 1 : currentValue - 1;
88    this.bookmarksCountTarget.flow.update(newValue);
89    this.bookmarkButtonTarget.classList.toggle("text-blue-500", this.bookmarksActive);
90    this.bookmarkIconTarget.classList.toggle("fill-blue-500", this.bookmarksActive);
91  }
92};

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.