PageSourceSearch

https://pkl-lang.org/_/js/theme-switcher.js

js pkl-lang.org collected 2026-09-24 18:03:30 UTC 3,252 bytes, 107 lines download raw bytes

1// ===----------------------------------------------------------------------===//
2// Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//	https://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15// ===----------------------------------------------------------------------===//
16
17/**
18 * Dark mode theme switcher
19 * Supports three modes: light, dark, and system (auto)
20 */
21;(function () {
22  'use strict'
23
24  const THEMES = {
25    LIGHT: 'light',
26    DARK: 'dark',
27    SYSTEM: 'system'
28  }
29
30  // Initialize theme on page load (before DOM is ready to avoid flash)
31  initializeTheme()
32
33  // Activate the dropdown once DOM is ready
34  document.addEventListener('DOMContentLoaded', function () {
35    activateDropdown(document.getElementById('theme-select'))
36  })
37
38  function initializeTheme() {
39    const savedTheme = getSavedTheme()
40    const effectiveTheme = getEffectiveTheme(savedTheme)
41
42    applyTheme(effectiveTheme)
43  }
44
45  function activateDropdown(select) {
46    if (!select) return
47
48    const savedTheme = getSavedTheme()
49    select.value = savedTheme
50
51    // Add change listener
52    select.addEventListener('change', onDropdownChange)
53  }
54
55  function onDropdownChange(event) {
56    const selectedTheme = event.target.value
57
58    saveTheme(selectedTheme)
59
60    const effectiveTheme = getEffectiveTheme(selectedTheme)
61    applyTheme(effectiveTheme)
62  }
63
64  function getEffectiveTheme(theme) {
65    // If system mode, determine based on system preference
66    if (theme === THEMES.SYSTEM || theme === null) {
67      const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
68      return prefersDark ? THEMES.DARK : THEMES.LIGHT
69    }
70    return theme
71  }
72
73  function applyTheme(theme) {
74    const isDark = theme === THEMES.DARK
75    document.documentElement.classList.toggle('dark-theme', isDark)
76    document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light')
77  }
78
79  function getSavedTheme() {
80    try {
81      return window.localStorage && window.localStorage.getItem('theme') || THEMES.SYSTEM
82    } catch (e) {
83      return THEMES.SYSTEM
84    }
85  }
86
87  function saveTheme(theme) {
88    try {
89      window.localStorage && window.localStorage.setItem('theme', theme)
90    } catch (e) {
91      // localStorage not available
92    }
93  }
94
95  // Listen for system theme changes (only when in system mode)
96  if (window.matchMedia) {
97    window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (e) {
98      const savedTheme = getSavedTheme()
99
100      // Only auto-switch if user is in system mode
101      if (savedTheme === THEMES.SYSTEM) {
102        const effectiveTheme = e.matches ? THEMES.DARK : THEMES.LIGHT
103        applyTheme(effectiveTheme)
104      }
105    })
106  }
107})()

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.