rastrillo / fiesta Public

Clone
git clone https://amadan.net/rastrillo/fiesta

Plain git — no account needed to clone.

Download

Download this file

1/*! Fiesta 1.2.0 | MPL-2.0 | https://fiesta.rastrillo.org */
2(function () {
3 "use strict";
4 if (window.fiestaShim) return;
5 window.fiestaShim = true;
6
7 var root = document.documentElement, KEY = "fiesta-scheme", SCHEME = "[rst-scheme],.rst-scheme";
8 var remembers = root.getAttribute("data-rst-scheme-store") === "local";
9
10 function stored() {
11 if (!remembers) return null;
12 try { return localStorage.getItem(KEY); } catch (e) { return null; }
13 }
14 function remember(s) {
15 if (!remembers) return;
16 try { if (s === "system") localStorage.removeItem(KEY); else localStorage.setItem(KEY, s); } catch (e) {}
17 }
18 function apply(s) {
19 if (s === "system") root.removeAttribute("data-theme"); else root.setAttribute("data-theme", s);
20 }
21 function mark(m, s) {
22 m.querySelectorAll("button").forEach(function (b) {
23 var f = b.form, v = f && f.elements.scheme && f.elements.scheme.value;
24 if (v === s) b.setAttribute("aria-current", "true"); else b.removeAttribute("aria-current");
25 });
26 }
27 function ready(fn) {
28 if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", fn); else fn();
29 }
30
31 var kept = root.hasAttribute("data-theme") ? null : stored();
32 if (kept === "light" || kept === "dark") {
33 apply(kept);
34 ready(function () { document.querySelectorAll(SCHEME).forEach(function (m) { mark(m, kept); }); });
35 }
36
37 var MENUS = "[rst-dropdown][open],[rst-menu-group][open],[rst-row-menu][open]";
38 MENUS += "," + MENUS.replace(/\[(rst[-\w]+)\]/g, ".$1");
39 MENUS += ",[rst-shell-topbar] [rst-shell-menu][open],[rst-shell-console~=page] [rst-shell-menu][open],[rst-shell-console~=index] [rst-shell-menu][open]";
40 MENUS += ",.rst-shell-topbar .rst-shell__menu[open],.rst-shell-console--page .rst-shell__menu[open],.rst-shell-console--index .rst-shell__menu[open]";
41 var TAIL = "[rst-shell-tail],.rst-shell__tail";
42
43 function menuAround(node) {
44 var d = node.closest(MENUS), t, s;
45 if (d) return d;
46 t = node.closest(TAIL);
47 d = t && t.previousElementSibling;
48 s = d && d.matches(MENUS) && d.querySelector("summary");
49 return s && s.getClientRects().length ? d : null;
50 }
51
52 function closeMenus(except) {
53 var keep = [], m;
54 for (m = except && except.closest && menuAround(except); m; m = m.parentElement && menuAround(m.parentElement)) keep.push(m);
55 document.querySelectorAll(MENUS).forEach(function (d) {
56 if (keep.indexOf(d) < 0 && !(except && d.contains(except))) d.open = false;
57 });
58 }
59
60 function dismissMenus(e) {
61 if (e.type === "click") { closeMenus(e.target); return; }
62 if (e.key !== "Escape") return;
63 var el = document.activeElement;
64 var host = el && el.closest ? menuAround(el) : null;
65 while (host && host.parentElement && menuAround(host.parentElement)) {
66 host = menuAround(host.parentElement);
67 }
68 closeMenus(null);
69 if (host) {
70 var summary = host.querySelector("summary");
71 if (summary) summary.focus();
72 }
73 }
74
75 document.addEventListener("click", dismissMenus, true);
76 document.addEventListener("keydown", dismissMenus, true);
77
78 var TRACK = "[rst-switch-track],.rst-switch__track", drag = null, after = null, settling = null, settleT = 0, releasing = false;
79 function unsettle() {
80 if (settling) settling.removeAttribute("data-rst-settle");
81 settling = null;
82 clearTimeout(settleT);
83 }
84 function settle(l) {
85 unsettle();
86 settling = l;
87 l.setAttribute("data-rst-settle", "");
88 settleT = setTimeout(unsettle, 300);
89 }
90 document.addEventListener("change", function (e) { if (settling && !releasing && settling.contains(e.target)) unsettle(); }, true);
91 document.addEventListener("pointerdown", function (e) {
92 if (drag && e.pointerId !== drag.id) return;
93 var t = e.target.closest && e.target.closest(TRACK), l = t && t.closest("[rst-switch],.rst-switch,[rst-tblock-head],.rst-tblock__head"), box = l && l.querySelector("input");
94 if (drag) drop({ type: "lost", pointerId: drag.id });
95 after = null;
96 if (!box || box.matches(":disabled") || e.button) return;
97 var r = t.getBoundingClientRect(), max = r.width - r.height;
98 drag = { l: l, t: t, box: box, id: e.pointerId, x: e.clientX, max: max, at: box.checked ? max : 0, pos: -1,
99 dir: getComputedStyle(t).direction === "rtl" ? -1 : 1 };
100 });
101 document.addEventListener("pointermove", function (e) {
102 var g = drag, d;
103 if (!g || e.pointerId !== g.id) return;
104 d = (e.clientX - g.x) * g.dir;
105 if (g.pos < 0) {
106 if (Math.abs(d) < 4) return;
107 if (settling === g.l) unsettle();
108 g.l.setAttribute("data-rst-drag", "");
109 g.t.setPointerCapture(e.pointerId);
110 }
111 g.pos = Math.min(g.max, Math.max(0, g.at + d));
112 d = g.pos / g.max;
113 g.t.style.setProperty("--rst-switch-p", d);
114 g.t.style.setProperty("--rst-switch-on", d * 100 + "%");
115 });
116 function drop(e) {
117 var g = drag;
118 if (!g || e.pointerId !== g.id) return;
119 drag = null;
120 if (g.pos < 0) return;
121 g.l.removeAttribute("data-rst-drag");
122 settle(g.l);
123 g.t.style.removeProperty("--rst-switch-p");
124 g.t.style.removeProperty("--rst-switch-on");
125 after = g.l;
126 releasing = true;
127 if (e.type === "pointerup" && !g.box.matches(":disabled") && g.pos >= g.max / 2 !== g.box.checked) g.box.click();
128 releasing = false;
129 }
130 document.addEventListener("pointerup", drop);
131 document.addEventListener("pointercancel", drop);
132 document.addEventListener("lostpointercapture", drop);
133 document.addEventListener("click", function (e) {
134 if (after && after.contains(e.target) && e.target.tagName !== "INPUT") {
135 e.preventDefault();
136 after = null;
137 }
138 }, true);
139
140 document.addEventListener("touchstart", function () {}, { passive: true });
141
142 document.addEventListener("submit", function (e) {
143 var f = e.target, m = f.closest(SCHEME), s = m && f.elements.scheme && f.elements.scheme.value;
144 if (!s) return;
145 e.preventDefault();
146 if (s !== "light" && s !== "dark") s = "system";
147 apply(s);
148 land();
149 remember(s);
150 mark(m, s);
151 m.open = false;
152 f.dispatchEvent(new CustomEvent("rst-scheme", { bubbles: true, detail: { scheme: s } }));
153 }, true);
154
155 function land() {
156 if (!document.getAnimations) return;
157 document.getAnimations().forEach(function (a) { if (typeof a.transitionProperty === "string") a.cancel(); });
158 }
159
160 var osScheme = window.matchMedia && matchMedia("(prefers-color-scheme: dark)");
161 if (osScheme) osScheme.onchange = function () { if (!root.hasAttribute("data-theme")) land(); };
162})();
163