appearance.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. ((function(global) {
  2. const DATA = JSON.parse(document.documentElement.dataset.appearance || 'null');
  3. const matchMedia = window.matchMedia('(prefers-color-scheme: dark)');
  4. try {
  5. // Chrome & Firefox
  6. matchMedia.addEventListener('change', (event) => {
  7. if (typhoonRetrieve().appearance === 'system') {
  8. typhoonSetTheme(event.matches ? 'dark' : 'light', true);
  9. }
  10. });
  11. } catch (fallback) {
  12. try {
  13. // Safari
  14. matchMedia.addListener((event) => {
  15. if (typhoonRetrieve().appearance === 'system') {
  16. typhoonSetTheme(event.matches ? 'dark' : 'light', true);
  17. }
  18. });
  19. } catch (error) {
  20. console.error(error);
  21. }
  22. }
  23. global.typhoonStore = function(data) {
  24. const STORAGE = DATA.store ? 'localStorage' : 'sessionStorage';
  25. const theme = data.appearance === 'system' ? typhoonGetTheme() : data.appearance;
  26. const config = Object.assign({}, typhoonRetrieve(), data, { theme: theme });
  27. global[STORAGE].setItem('typhoon-appearance', JSON.stringify(config));
  28. typhoonSetTheme(theme, false);
  29. }
  30. global.typhoonRetrieve = function() {
  31. const STORAGE = DATA.store ? 'localStorage' : 'sessionStorage';
  32. const systemTheme = typhoonGetTheme();
  33. const storage = JSON.parse(global[STORAGE].getItem('typhoon-appearance') || 'null');
  34. if (storage && storage.appearance === 'system') {
  35. storage.theme = systemTheme;
  36. }
  37. return storage || {
  38. theme: DATA.appearance === 'system' ? systemTheme : DATA.appearance,
  39. appearance: DATA.appearance || 'system'
  40. };
  41. }
  42. global.typhoonSetTheme = function(theme, store) {
  43. const event = new CustomEvent('typhoon-theme', {
  44. detail: {
  45. theme: theme,
  46. appearance: typhoonRetrieve().appearance
  47. }
  48. });
  49. if (store) {
  50. typhoonStore({ theme: theme || typhoonGetTheme() });
  51. }
  52. window.dispatchEvent(event);
  53. }
  54. global.typhoonGetTheme = function() {
  55. return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
  56. }
  57. })(window));