-
Notifications
You must be signed in to change notification settings - Fork 313
Expand file tree
/
Copy pathindex.js
More file actions
executable file
·129 lines (113 loc) · 4.04 KB
/
index.js
File metadata and controls
executable file
·129 lines (113 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { html, define } from 'hybrids';
import style from './style.less?inline';
import moonIcon from '@images/moon.svg?raw';
import sunIcon from '@images/sun.svg?raw';
import desktopIcon from '@images/desktop.svg?raw';
import { watchHtmlMode } from '@utils';
export const SYSTEM_MODE = 'system';
export const isDark = () =>
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
const storageChangeEvent = new CustomEvent('storageChange');
function toggleTheme(_host, currentTheme) {
document.documentElement.removeAttribute('theme-mode');
if (currentTheme === SYSTEM_MODE) {
currentTheme = isDark();
}
document.documentElement.setAttribute('theme-mode', currentTheme);
}
function handleTabClick(host, _event, currentTheme) {
const root = document.documentElement;
const prevTheme = root.getAttribute('theme-mode');
Object.assign(host, { theme: currentTheme });
if ((currentTheme === SYSTEM_MODE && isDark() === prevTheme) || prevTheme === currentTheme) return;
if (!document.startViewTransition) return toggleTheme(host, currentTheme);
document.startViewTransition(() => toggleTheme(host, currentTheme));
}
function initBlockStyleMap(host) {
requestAnimationFrame(() => {
const { shadowRoot } = host;
const items = shadowRoot.querySelectorAll('.item');
let styleMap = {};
items.forEach((item) => {
if (!item.offsetWidth) {
styleMap = null;
} else {
const { theme } = item.dataset;
styleMap[theme] = {
width: `${item.offsetWidth}px`,
left: `${item.offsetLeft}px`,
};
}
});
Object.assign(host, { blockStyleMap: styleMap });
});
}
export default define({
tag: 'td-theme-tabs',
theme: {
get: (_host, lastValue) => lastValue || 'light',
set: (_host, value) => {
if (value) {
localStorage.setItem('--tdesign-theme', value);
window.dispatchEvent(storageChangeEvent);
}
return value;
},
connect: (host, key, invalidate) => {
const lastTheme = localStorage.getItem('--tdesign-theme');
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handler = () => {
if (host.theme !== SYSTEM_MODE) return;
toggleTheme(host, SYSTEM_MODE);
};
if (lastTheme) {
document.documentElement.removeAttribute('theme-mode');
Object.assign(host, { [key]: lastTheme });
document.documentElement.setAttribute('theme-mode', lastTheme === SYSTEM_MODE ? isDark() : lastTheme);
invalidate();
}
const observer = watchHtmlMode((themeMode) => {
if (host.theme === SYSTEM_MODE) return;
Object.assign(host, { [key]: themeMode });
});
mediaQuery.addEventListener('change', handler, { passive: true });
handler();
return () => {
observer.disconnect();
mediaQuery.removeEventListener('change', handler);
};
},
},
blockStyleMap: {
get: (_host, lastValue) => lastValue || undefined,
set: (_host, value) => value,
},
render: (host) => {
const { theme, blockStyleMap } = host;
if (!blockStyleMap) initBlockStyleMap(host);
const blockStyle = blockStyleMap ? blockStyleMap[theme] : {};
return html`
<div class="TDesign-theme-tabs">
<div class="TDesign-theme-tabs__block" style=${blockStyle || {}}></div>
<div
onclick=${(host, e) => handleTabClick(host, e, SYSTEM_MODE)}
data-theme="system"
class="item system ${theme === SYSTEM_MODE ? 'active' : ''}"
innerHTML=${desktopIcon}
></div>
<div
onclick=${(host, e) => handleTabClick(host, e, 'light')}
data-theme="light"
class="item sun ${theme === 'light' ? 'active' : ''}"
innerHTML=${sunIcon}
></div>
<div
onclick=${(host, e) => handleTabClick(host, e, 'dark')}
data-theme="dark"
class="item moon ${theme === 'dark' ? 'active' : ''}"
innerHTML=${moonIcon}
></div>
</div>
`.css`${style}`;
},
});