PageSourceSearch

https://hackorum.dev/assets/controllers/theme_controller-75486c88.js

js hackorum.dev collected 2026-09-28 07:00:47 UTC 2,126 bytes, 71 lines download raw bytes

1import { Controller } from "@hotwired/stimulus"
2
3const STORAGE_KEY = "hackorum-theme"
4const DEFAULT_THEME = "light"
5
6export default class extends Controller {
7  static targets = ["icon", "label", "button"]
8
9  connect() {
10    this.applyInitialTheme()
11  }
12
13  toggle(event) {
14    if (event && event.type !== "change") {
15      event.preventDefault()
16    }
17    const nextTheme = this.currentTheme === "dark" ? "light" : "dark"
18    this.setTheme(nextTheme)
19  }
20
21  select(event) {
22    event.preventDefault()
23    const { themeValue } = event.currentTarget.dataset
24    this.setTheme(themeValue)
25  }
26
27  applyInitialTheme() {
28    const storedTheme = window.localStorage.getItem(STORAGE_KEY)
29    const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches
30    const initialTheme = storedTheme || (prefersDark ? "dark" : DEFAULT_THEME)
31
32    this.setTheme(initialTheme, { persist: false })
33  }
34
35  setTheme(theme, { persist = true } = {}) {
36    const normalizedTheme = theme === "dark" ? "dark" : "light"
37    document.documentElement.dataset.theme = normalizedTheme
38
39    if (persist) {
40      window.localStorage.setItem(STORAGE_KEY, normalizedTheme)
41    }
42
43    this.updateToggle(normalizedTheme)
44  }
45
46  updateToggle(theme) {
47    if (this.hasLabelTarget) {
48      this.labelTarget.textContent = theme === "dark" ? "Dark" : "Light"
49    }
50
51    if (this.hasIconTarget) {
52      this.iconTarget.classList.remove("fa-regular", "fa-solid", "fa-moon", "fa-sun")
53      this.iconTarget.classList.add("fa-solid")
54      this.iconTarget.classList.add(theme === "dark" ? "fa-sun" : "fa-moon")
55    }
56
57    this.element.setAttribute("aria-pressed", theme === "dark")
58    this.element.setAttribute("aria-label", `Switch to ${theme === "dark" ? "light" : "dark"} mode`)
59    this.element.setAttribute("title", `Switch to ${theme === "dark" ? "light" : "dark"} mode`)
60
61    if (this.hasButtonTarget) {
62      this.buttonTargets.forEach((button) => {
63        button.classList.toggle("is-active", button.dataset.themeValue === theme)
64      })
65    }
66  }
67
68  get currentTheme() {
69    return document.documentElement.dataset.theme || DEFAULT_THEME
70  }
71}

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.