@slidev-polls/shared 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,61 @@
1
+ :root {
2
+ --sp-bg: #ffffff;
3
+ --sp-bg-muted: #fafafa;
4
+ --sp-bg-subtle: #f4f4f5;
5
+ --sp-fg: #0a0a0a;
6
+ --sp-fg-muted: #52525b;
7
+ --sp-fg-subtle: #737373;
8
+ --sp-fg-faint: #a1a1aa;
9
+ --sp-border: #e5e5e5;
10
+ --sp-border-strong: #d4d4d8;
11
+ --sp-accent: #7c3aed;
12
+ --sp-accent-fg: #ffffff;
13
+ --sp-accent-soft: #ede9fe;
14
+ --sp-accent-ring: rgba(124, 58, 237, 0.4);
15
+ --sp-success: #16a34a;
16
+ --sp-success-bg: #dcfce7;
17
+ --sp-success-fg: #166534;
18
+ --sp-danger: #dc2626;
19
+ --sp-danger-bg: #fef2f2;
20
+ --sp-danger-fg: #991b1b;
21
+ --sp-radius-sm: 6px;
22
+ --sp-radius: 8px;
23
+ --sp-radius-lg: 10px;
24
+ --sp-radius-xl: 14px;
25
+ --sp-font-sans: "Inter", -apple-system, system-ui, sans-serif;
26
+ --sp-font-mono: "JetBrains Mono", ui-monospace, "SF Mono", monospace;
27
+ --sp-ease: cubic-bezier(0.22, 1, 0.36, 1);
28
+ --sp-dur: 400ms;
29
+ }
30
+
31
+ [data-theme="dark"] {
32
+ --sp-bg: #0a0a0a;
33
+ --sp-bg-muted: #18181b;
34
+ --sp-bg-subtle: #27272a;
35
+ --sp-fg: #fafafa;
36
+ --sp-fg-muted: #d4d4d8;
37
+ --sp-fg-subtle: #a1a1aa;
38
+ --sp-fg-faint: #71717a;
39
+ --sp-border: #27272a;
40
+ --sp-border-strong: #3f3f46;
41
+ --sp-accent: #a78bfa;
42
+ --sp-accent-fg: #0a0a0a;
43
+ /* Translucent accent so non-leader bars in ResultsPanel sit visibly above
44
+ the row background (--sp-bg-subtle = #27272a). The previous flat #3f3f46
45
+ was within ~10% lightness of the row and disappeared on dark slides. */
46
+ --sp-accent-soft: rgba(167, 139, 250, 0.28);
47
+ --sp-accent-ring: rgba(167, 139, 250, 0.4);
48
+ --sp-success: #22c55e;
49
+ --sp-success-bg: rgba(34, 197, 94, 0.15);
50
+ --sp-success-fg: #86efac;
51
+ --sp-danger: #ef4444;
52
+ --sp-danger-bg: rgba(239, 68, 68, 0.12);
53
+ --sp-danger-fg: #fca5a5;
54
+ }
55
+
56
+ @media (prefers-reduced-motion: reduce) {
57
+ :root,
58
+ [data-theme="dark"] {
59
+ --sp-dur: 0ms;
60
+ }
61
+ }
@@ -0,0 +1,78 @@
1
+ import { ref, watch, type Ref } from "vue";
2
+
3
+ export type ThemeMode = "light" | "dark";
4
+
5
+ const STORAGE_KEY = "sp-theme";
6
+
7
+ let modeRef: Ref<ThemeMode> | null = null;
8
+ let mediaQuery: MediaQueryList | null = null;
9
+ let mediaListener: ((e: MediaQueryListEvent) => void) | null = null;
10
+
11
+ function readOverride(): ThemeMode | null {
12
+ try {
13
+ const v = localStorage.getItem(STORAGE_KEY);
14
+ return v === "light" || v === "dark" ? v : null;
15
+ } catch {
16
+ return null;
17
+ }
18
+ }
19
+
20
+ function osPrefersDark(): boolean {
21
+ return window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
22
+ }
23
+
24
+ function apply(mode: ThemeMode) {
25
+ document.documentElement.setAttribute("data-theme", mode);
26
+ }
27
+
28
+ export function useTheme() {
29
+ if (modeRef) {
30
+ return {
31
+ mode: modeRef,
32
+ setMode,
33
+ toggle
34
+ };
35
+ }
36
+
37
+ const initial: ThemeMode = readOverride() ?? (osPrefersDark() ? "dark" : "light");
38
+ modeRef = ref<ThemeMode>(initial);
39
+ apply(initial);
40
+
41
+ watch(modeRef, (m) => apply(m));
42
+
43
+ mediaQuery = window.matchMedia?.("(prefers-color-scheme: dark)") ?? null;
44
+ if (mediaQuery) {
45
+ mediaListener = (e) => {
46
+ if (readOverride() !== null) return;
47
+ modeRef!.value = e.matches ? "dark" : "light";
48
+ };
49
+ mediaQuery.addEventListener("change", mediaListener);
50
+ }
51
+
52
+ return { mode: modeRef, setMode, toggle };
53
+ }
54
+
55
+ function setMode(m: ThemeMode) {
56
+ if (!modeRef) return;
57
+ modeRef.value = m;
58
+ apply(m);
59
+ try {
60
+ localStorage.setItem(STORAGE_KEY, m);
61
+ } catch {
62
+ /* noop */
63
+ }
64
+ }
65
+
66
+ function toggle() {
67
+ if (!modeRef) return;
68
+ setMode(modeRef.value === "light" ? "dark" : "light");
69
+ }
70
+
71
+ export function __resetThemeForTests() {
72
+ if (mediaQuery && mediaListener) {
73
+ mediaQuery.removeEventListener("change", mediaListener);
74
+ }
75
+ modeRef = null;
76
+ mediaQuery = null;
77
+ mediaListener = null;
78
+ }