PageSourceSearch

https://preline.co/assets/js/hs-theme-main-demo.js

js preline.co collected 2026-09-25 19:17:46 UTC 4,781 bytes, 164 lines download raw bytes

1function generateThemeVariables(
2  theme = "default",
3  brand = "blue",
4  target = document.querySelector("head"),
5  styleId = "#hs-brand-variables",
6  id = "hs-brand-variables"
7) {
8  let style = null;
9
10  if (!target.querySelector(styleId)) {
11    style = document.createElement("style");
12    style.id = id;
13
14    target.append(style);
15  } else {
16    style = target.querySelector(styleId);
17  }
18
19  style.textContent = `
20    :root[data-theme="theme-${theme}"],
21    [data-theme="theme-${theme}"] {
22      --primary-50:       var(--color-${brand}-50);
23      --primary-100:      var(--color-${brand}-100);
24      --primary-200:      var(--color-${brand}-200);
25      --primary-300:      var(--color-${brand}-300);
26      --primary-400:      var(--color-${brand}-400);
27      --primary-500:      var(--color-${brand}-500);
28      --primary-600:      var(--color-${brand}-600);
29      --primary-700:      var(--color-${brand}-700);
30      --primary-800:      var(--color-${brand}-800);
31      --primary-900:      var(--color-${brand}-900);
32      --primary-950:      var(--color-${brand}-950);
33    }
34  `;
35}
36
37document.addEventListener('DOMContentLoaded', function () {
38  const themeSwitcher = document.querySelector('#hs-themes');
39  const brandSwitcher = document.querySelector('#hs-brands');
40  const fontSwitcher = document.querySelector('#hs-fonts');
41  const appearanceSwitcher = document.querySelector('#hs-appearance');
42  const iframeEl = document.querySelector('#hs-theme-main-demo-iframe');
43
44  if (
45    !themeSwitcher ||
46    !brandSwitcher ||
47    !fontSwitcher ||
48    !appearanceSwitcher ||
49    !iframeEl
50  ) {
51    return;
52  }
53  
54  let currentTheme = themeSwitcher.value || 'default';
55  let currentBrand = brandSwitcher.value || 'blue';
56  let currentFont = fontSwitcher.value || 'sans';
57  let currentAppearance = 'light';
58  
59  const themesDefaults = {
60    "default": "blue",
61    "harvest": "amber",
62    "retro": "fuchsia",
63    "ocean": "cyan",
64    "autumn": "yellow",
65    "moon": "gray",
66    "bubblegum": "pink",
67    "cashmere": "preline-mauve",
68    "olive": "preline-avocado",
69  };
70
71  const dispatchToIframe = (type, value) => {
72    if (!iframeEl.contentWindow) return false;
73    
74    iframeEl.contentWindow.postMessage({ type, value }, "*");
75  };
76  const withIframe = (callback) => {
77    if (!iframeEl || !iframeEl.contentWindow || !iframeEl.contentWindow.document) return false;
78    const iframeDoc = iframeEl.contentWindow.document;
79
80    if (iframeDoc.readyState !== 'complete') return false;
81
82    callback(iframeDoc);
83    return true;
84  };
85
86  const applyAppearance = (appearance) => {
87    currentAppearance = appearance;
88
89    withIframe((iframeDoc) => {
90      const html = iframeDoc.documentElement;
91      const head = iframeDoc.head;
92
93      html.classList.remove("light", "dark", "auto");
94      html.classList.add(currentAppearance);
95      generateThemeVariables(currentTheme, currentBrand, head);
96      dispatchToIframe("hs:appearance-change", currentAppearance);
97    });
98  };
99
100  const syncTheme = () => {
101    withIframe((iframeDoc) => {
102      const html = iframeDoc.documentElement;
103      const head = iframeDoc.head;
104
105      html.setAttribute('data-theme', `theme-${currentTheme}`);
106      html.setAttribute('data-brand', currentBrand);
107      html.setAttribute('data-font', currentFont);
108      generateThemeVariables(currentTheme, currentBrand, head);
109      dispatchToIframe("hs:color-theme-change", currentTheme);
110      dispatchToIframe("hs:brand-change", currentBrand);
111      dispatchToIframe("hs:font-change", currentFont);
112    });
113  };
114
115  themeSwitcher.addEventListener('change', function () {
116    const brandSwitcherInstance = HSSelect.getInstance(brandSwitcher, true);
117    currentTheme = this.value;
118    currentBrand = themesDefaults[currentTheme];
119    
120    brandSwitcherInstance.element.setValue(currentBrand);
121    syncTheme();
122  });
123
124  brandSwitcher.addEventListener('change', function () {
125    currentBrand = this.value;
126    
127    syncTheme();
128  });
129
130  fontSwitcher.addEventListener('change', function () {
131    currentFont = this.value;
132    
133    syncTheme();
134  });
135  
136  appearanceSwitcher.addEventListener('change', function () {
137    applyAppearance(this.checked ? "dark" : "light");
138  });
139  
140  window.addEventListener('on-hs-appearance-change', (evt) => {
141    const nextAppearance = evt.detail;
142    
143    appearanceSwitcher.checked = nextAppearance === "dark";
144    appearanceSwitcher.disabled = nextAppearance === "dark";
145    
146    applyAppearance(nextAppearance);
147  });
148
149  if (iframeEl) {
150    const initSync = () => {
151      const isReady = withIframe(() => {
152        syncTheme();
153        applyAppearance(currentAppearance);
154      });
155
156      if (!isReady) {
157        setTimeout(initSync, 50);
158      }
159    };
160
161    iframeEl.addEventListener('load', initSync);
162    initSync();
163  }
164});

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.