diff --git a/src/App.jsx b/src/App.jsx
index 61b260b2..023f5579 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -22,7 +22,7 @@ const useAppSetup = () => {
loadSettings();
const refreshHandler = (data) => {
- if (data === 'other') {
+ if (data === 'other' || data === 'greeting' || data === 'clock' || data === 'quote') {
loadSettings(true);
}
};
diff --git a/src/components/Form/Settings/ChipSelect/ChipSelect.jsx b/src/components/Form/Settings/ChipSelect/ChipSelect.jsx
index 9d76eab0..65ad3c1b 100644
--- a/src/components/Form/Settings/ChipSelect/ChipSelect.jsx
+++ b/src/components/Form/Settings/ChipSelect/ChipSelect.jsx
@@ -29,6 +29,26 @@ function ChipSelect({ label, options, onChange, name }) {
useEffect(() => {
const handleClickOutside = (event) => {
+ // Ignore clicks on color inputs to prevent closing when native color picker opens
+ if (event.target.type === 'color') {
+ return;
+ }
+
+ // Also ignore clicks on color input labels and wrappers
+ const target = event.target;
+ if (target.tagName === 'LABEL' && target.htmlFor) {
+ const associatedInput = document.getElementById(target.htmlFor) || document.querySelector(`input[name="${target.htmlFor}"]`);
+ if (associatedInput && associatedInput.type === 'color') {
+ return;
+ }
+ }
+
+ // Check if clicking within a color input wrapper
+ const colorInputWrapper = target.closest('.colourInput');
+ if (colorInputWrapper && colorInputWrapper.querySelector('input[type="color"]')) {
+ return;
+ }
+
if (
containerRef.current &&
!containerRef.current.contains(event.target) &&
diff --git a/src/components/Form/Settings/DatePicker/DatePicker.jsx b/src/components/Form/Settings/DatePicker/DatePicker.jsx
index 75f0add4..add10dec 100644
--- a/src/components/Form/Settings/DatePicker/DatePicker.jsx
+++ b/src/components/Form/Settings/DatePicker/DatePicker.jsx
@@ -23,6 +23,26 @@ const DatePicker = memo((props) => {
useEffect(() => {
const handleClickOutside = (event) => {
+ // Ignore clicks on color inputs to prevent closing when native color picker opens
+ if (event.target.type === 'color') {
+ return;
+ }
+
+ // Also ignore clicks on color input labels and wrappers
+ const target = event.target;
+ if (target.tagName === 'LABEL' && target.htmlFor) {
+ const associatedInput = document.getElementById(target.htmlFor) || document.querySelector(`input[name="${target.htmlFor}"]`);
+ if (associatedInput && associatedInput.type === 'color') {
+ return;
+ }
+ }
+
+ // Check if clicking within a color input wrapper
+ const colorInputWrapper = target.closest('.colourInput');
+ if (colorInputWrapper && colorInputWrapper.querySelector('input[type="color"]')) {
+ return;
+ }
+
if (
containerRef.current &&
!containerRef.current.contains(event.target) &&
diff --git a/src/components/Form/Settings/Dropdown/Dropdown.jsx b/src/components/Form/Settings/Dropdown/Dropdown.jsx
index e0c1eb98..7c8832b5 100644
--- a/src/components/Form/Settings/Dropdown/Dropdown.jsx
+++ b/src/components/Form/Settings/Dropdown/Dropdown.jsx
@@ -35,6 +35,26 @@ const Dropdown = memo((props) => {
useEffect(() => {
const handleClickOutside = (event) => {
+ // Ignore clicks on color inputs to prevent closing when native color picker opens
+ if (event.target.type === 'color') {
+ return;
+ }
+
+ // Also ignore clicks on color input labels and wrappers
+ const target = event.target;
+ if (target.tagName === 'LABEL' && target.htmlFor) {
+ const associatedInput = document.getElementById(target.htmlFor) || document.querySelector(`input[name="${target.htmlFor}"]`);
+ if (associatedInput && associatedInput.type === 'color') {
+ return;
+ }
+ }
+
+ // Check if clicking within a color input wrapper
+ const colorInputWrapper = target.closest('.colourInput');
+ if (colorInputWrapper && colorInputWrapper.querySelector('input[type="color"]')) {
+ return;
+ }
+
if (
containerRef.current &&
!containerRef.current.contains(event.target) &&
diff --git a/src/components/Form/Settings/LocationSearch/LocationSearch.jsx b/src/components/Form/Settings/LocationSearch/LocationSearch.jsx
index 2b27160a..7ffcdb1c 100644
--- a/src/components/Form/Settings/LocationSearch/LocationSearch.jsx
+++ b/src/components/Form/Settings/LocationSearch/LocationSearch.jsx
@@ -52,6 +52,26 @@ const LocationSearch = memo((props) => {
useEffect(() => {
const handleClickOutside = (event) => {
+ // Ignore clicks on color inputs to prevent closing when native color picker opens
+ if (event.target.type === 'color') {
+ return;
+ }
+
+ // Also ignore clicks on color input labels and wrappers
+ const target = event.target;
+ if (target.tagName === 'LABEL' && target.htmlFor) {
+ const associatedInput = document.getElementById(target.htmlFor) || document.querySelector(`input[name="${target.htmlFor}"]`);
+ if (associatedInput && associatedInput.type === 'color') {
+ return;
+ }
+ }
+
+ // Check if clicking within a color input wrapper
+ const colorInputWrapper = target.closest('.colourInput');
+ if (colorInputWrapper && colorInputWrapper.querySelector('input[type="color"]')) {
+ return;
+ }
+
const t = useT();
if (
containerRef.current &&
diff --git a/src/features/greeting/Greeting.jsx b/src/features/greeting/Greeting.jsx
index 46bbe9a8..e933b4db 100644
--- a/src/features/greeting/Greeting.jsx
+++ b/src/features/greeting/Greeting.jsx
@@ -141,7 +141,7 @@ const Greeting = () => {
EventBus.on('refresh', handleRefresh);
return () => {
- EventBus.off('refresh');
+ EventBus.off('refresh', handleRefresh);
if (timerRef.current) {
clearTimeout(timerRef.current);
}
diff --git a/src/features/greeting/options/GreetingOptions.jsx b/src/features/greeting/options/GreetingOptions.jsx
index 912b2c64..ed6dcacb 100644
--- a/src/features/greeting/options/GreetingOptions.jsx
+++ b/src/features/greeting/options/GreetingOptions.jsx
@@ -273,12 +273,12 @@ const GreetingOptions = ({ currentSubSection, onSubSectionChange, sectionName })
name="greetingFontWeight"
category="greeting"
items={[
- { value: '400', text: t(fontWeight + '.normal') },
+ { value: '600', text: t(fontWeight + '.semi_bold') },
{ value: '100', text: t(fontWeight + '.thin') },
{ value: '200', text: t(fontWeight + '.extra_light') },
{ value: '300', text: t(fontWeight + '.light') },
+ { value: '400', text: t(fontWeight + '.normal') },
{ value: '500', text: t(fontWeight + '.medium') },
- { value: '600', text: t(fontWeight + '.semi_bold') },
{ value: '700', text: t(fontWeight + '.bold') },
{ value: '800', text: t(fontWeight + '.extra_bold') },
]}
diff --git a/src/features/message/Message.jsx b/src/features/message/Message.jsx
index d7dd5070..f5933d7b 100644
--- a/src/features/message/Message.jsx
+++ b/src/features/message/Message.jsx
@@ -26,7 +26,7 @@ const Message = () => {
EventBus.on('refresh', handleRefresh);
return () => {
- EventBus.off('refresh');
+ EventBus.off('refresh', handleRefresh);
};
}, []);
diff --git a/src/features/misc/views/Widgets.jsx b/src/features/misc/views/Widgets.jsx
index 07ba8764..48d883b9 100644
--- a/src/features/misc/views/Widgets.jsx
+++ b/src/features/misc/views/Widgets.jsx
@@ -63,7 +63,7 @@ const Widgets = () => {
EventBus.on('refresh', handleRefresh);
return () => {
- EventBus.off('refresh');
+ EventBus.off('refresh', handleRefresh);
};
}, []);
diff --git a/src/features/navbar/Navbar.jsx b/src/features/navbar/Navbar.jsx
index dd7388b4..ef639158 100644
--- a/src/features/navbar/Navbar.jsx
+++ b/src/features/navbar/Navbar.jsx
@@ -67,7 +67,7 @@ const Navbar = ({ openModal }) => {
EventBus.on('refresh', handleRefresh);
return () => {
- EventBus.off('refresh');
+ EventBus.off('refresh', handleRefresh);
};
}, []);
diff --git a/src/features/navbar/components/Notes.jsx b/src/features/navbar/components/Notes.jsx
index abb13122..76335624 100644
--- a/src/features/navbar/components/Notes.jsx
+++ b/src/features/navbar/components/Notes.jsx
@@ -28,7 +28,7 @@ const Notes = ({ notesRef, floatRef, position, xPosition, yPosition }) => {
EventBus.on('refresh', handleRefresh);
return () => {
- EventBus.off('refresh');
+ EventBus.off('refresh', handleRefresh);
};
}, []);
diff --git a/src/features/quote/options/QuoteOptions.jsx b/src/features/quote/options/QuoteOptions.jsx
index a62e8d7c..0d77d172 100644
--- a/src/features/quote/options/QuoteOptions.jsx
+++ b/src/features/quote/options/QuoteOptions.jsx
@@ -232,12 +232,12 @@ const QuoteOptions = ({ currentSubSection, onSubSectionChange, sectionName }) =>
name="quoteFontWeight"
category="quote"
items={[
- { value: '400', text: t(fontWeight + '.normal') },
+ { value: '600', text: t(fontWeight + '.semi_bold') },
{ value: '100', text: t(fontWeight + '.thin') },
{ value: '200', text: t(fontWeight + '.extra_light') },
{ value: '300', text: t(fontWeight + '.light') },
+ { value: '400', text: t(fontWeight + '.normal') },
{ value: '500', text: t(fontWeight + '.medium') },
- { value: '600', text: t(fontWeight + '.semi_bold') },
{ value: '700', text: t(fontWeight + '.bold') },
{ value: '800', text: t(fontWeight + '.extra_bold') },
]}
diff --git a/src/features/search/Search.jsx b/src/features/search/Search.jsx
index dc81df98..b4b05cf1 100644
--- a/src/features/search/Search.jsx
+++ b/src/features/search/Search.jsx
@@ -81,11 +81,16 @@ function Search() {
}
}
- EventBus.on('refresh', (data) => {
+ const handleRefresh = (data) => {
if (data === 'search') {
init();
}
- });
+ };
+
+ EventBus.on('refresh', handleRefresh);
+ return () => {
+ EventBus.off('refresh', handleRefresh);
+ };
}, [init]);
function searchButton(e) {
diff --git a/src/features/search/components/autocomplete/Autocomplete.jsx b/src/features/search/components/autocomplete/Autocomplete.jsx
index 85114296..0a541a56 100644
--- a/src/features/search/components/autocomplete/Autocomplete.jsx
+++ b/src/features/search/components/autocomplete/Autocomplete.jsx
@@ -54,7 +54,7 @@ const Autocomplete = ({
EventBus.on('refresh', handleRefresh);
return () => {
- EventBus.off('refresh');
+ EventBus.off('refresh', handleRefresh);
};
}, []);
diff --git a/src/features/time/Clock.jsx b/src/features/time/Clock.jsx
index eff7c869..d1a1d17e 100644
--- a/src/features/time/Clock.jsx
+++ b/src/features/time/Clock.jsx
@@ -135,7 +135,7 @@ const Clock = () => {
EventBus.on('refresh', handleRefresh);
return () => {
- EventBus.off('refresh');
+ EventBus.off('refresh', handleRefresh);
if (timerRef.current) {
clearTimeout(timerRef.current);
}
diff --git a/src/features/time/Date.jsx b/src/features/time/Date.jsx
index ce306089..b9bca448 100644
--- a/src/features/time/Date.jsx
+++ b/src/features/time/Date.jsx
@@ -143,7 +143,7 @@ const DateWidget = () => {
EventBus.on('refresh', handleRefresh);
return () => {
- EventBus.off('refresh');
+ EventBus.off('refresh', handleRefresh);
};
}, []);
diff --git a/src/features/time/options/TimeOptions.jsx b/src/features/time/options/TimeOptions.jsx
index 87b42b78..db4d0686 100644
--- a/src/features/time/options/TimeOptions.jsx
+++ b/src/features/time/options/TimeOptions.jsx
@@ -253,12 +253,12 @@ const TimeOptions = ({ currentSubSection, onSubSectionChange, sectionName }) =>
name="clockFontWeight"
category="clock"
items={[
- { value: '400', text: t(fontWeight + '.normal') },
+ { value: '600', text: t(fontWeight + '.semi_bold') },
{ value: '100', text: t(fontWeight + '.thin') },
{ value: '200', text: t(fontWeight + '.extra_light') },
{ value: '300', text: t(fontWeight + '.light') },
+ { value: '400', text: t(fontWeight + '.normal') },
{ value: '500', text: t(fontWeight + '.medium') },
- { value: '600', text: t(fontWeight + '.semi_bold') },
{ value: '700', text: t(fontWeight + '.bold') },
{ value: '800', text: t(fontWeight + '.extra_bold') },
]}
diff --git a/src/utils/settings/load.js b/src/utils/settings/load.js
index 07cf9138..09ca611e 100644
--- a/src/utils/settings/load.js
+++ b/src/utils/settings/load.js
@@ -143,113 +143,104 @@ export function loadSettings(hotreload) {
// Per-widget fonts (override global widget font)
const greetingFont = localStorage.getItem('greetingFont');
- if (greetingFont) {
- const greetingFontWeight = localStorage.getItem('greetingFontWeight') || '400';
- const greetingFontStyle = localStorage.getItem('greetingFontStyle') || 'normal';
- const greetingColor = localStorage.getItem('greetingColor') || '#ffffff';
+ const greetingFontWeight = localStorage.getItem('greetingFontWeight');
+ const greetingFontStyle = localStorage.getItem('greetingFontStyle');
+ const greetingColor = localStorage.getItem('greetingColor');
- const fontFamily = greetingFont.replace(/ /g, '+');
- const googleFontUrl = `@import url('https://fonts.googleapis.com/css2?family=${fontFamily}:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');`;
+ if (greetingFont || greetingFontWeight || greetingFontStyle || greetingColor) {
+ let styleContent = '';
+
+ if (greetingFont) {
+ const fontFamily = greetingFont.replace(/ /g, '+');
+ styleContent += `@import url('https://fonts.googleapis.com/css2?family=${fontFamily}:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');\n`;
+ }
+
+ styleContent += '.greeting {';
+ if (greetingFont) {
+ styleContent += `font-family: '${greetingFont}', 'Lexend Deca', 'Inter', sans-serif !important;`;
+ }
+ if (greetingFontWeight) {
+ styleContent += `font-weight: ${greetingFontWeight} !important;`;
+ }
+ if (greetingFontStyle) {
+ styleContent += `font-style: ${greetingFontStyle} !important;`;
+ }
+ if (greetingColor) {
+ styleContent += `color: ${greetingColor} !important;`;
+ }
+ styleContent += '}';
document.head.insertAdjacentHTML(
'beforeend',
- `
-
- `,
- );
- } else if (localStorage.getItem('greetingColor')) {
- const greetingColor = localStorage.getItem('greetingColor');
- document.head.insertAdjacentHTML(
- 'beforeend',
- `
-
- `,
+ ``,
);
}
const clockFont = localStorage.getItem('clockFont');
- if (clockFont) {
- const clockFontWeight = localStorage.getItem('clockFontWeight') || '400';
- const clockFontStyle = localStorage.getItem('clockFontStyle') || 'normal';
- const clockColor = localStorage.getItem('clockColor') || '#ffffff';
+ const clockFontWeight = localStorage.getItem('clockFontWeight');
+ const clockFontStyle = localStorage.getItem('clockFontStyle');
+ const clockColor = localStorage.getItem('clockColor');
- const fontFamily = clockFont.replace(/ /g, '+');
- const googleFontUrl = `@import url('https://fonts.googleapis.com/css2?family=${fontFamily}:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');`;
+ if (clockFont || clockFontWeight || clockFontStyle || clockColor) {
+ let styleContent = '';
+
+ if (clockFont) {
+ const fontFamily = clockFont.replace(/ /g, '+');
+ styleContent += `@import url('https://fonts.googleapis.com/css2?family=${fontFamily}:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');\n`;
+ }
+
+ styleContent += '.clock, .date {';
+ if (clockFont) {
+ styleContent += `font-family: '${clockFont}', 'Lexend Deca', 'Inter', sans-serif !important;`;
+ }
+ if (clockFontWeight) {
+ styleContent += `font-weight: ${clockFontWeight} !important;`;
+ }
+ if (clockFontStyle) {
+ styleContent += `font-style: ${clockFontStyle} !important;`;
+ }
+ if (clockColor) {
+ styleContent += `color: ${clockColor} !important;`;
+ }
+ styleContent += '}';
document.head.insertAdjacentHTML(
'beforeend',
- `
-
- `,
- );
- } else if (localStorage.getItem('clockColor')) {
- const clockColor = localStorage.getItem('clockColor');
- document.head.insertAdjacentHTML(
- 'beforeend',
- `
-
- `,
+ ``,
);
}
const quoteFont = localStorage.getItem('quoteFont');
- if (quoteFont) {
- const quoteFontWeight = localStorage.getItem('quoteFontWeight') || '400';
- const quoteFontStyle = localStorage.getItem('quoteFontStyle') || 'normal';
- const quoteColor = localStorage.getItem('quoteColor') || '#ffffff';
+ const quoteFontWeight = localStorage.getItem('quoteFontWeight');
+ const quoteFontStyle = localStorage.getItem('quoteFontStyle');
+ const quoteColor = localStorage.getItem('quoteColor');
- const fontFamily = quoteFont.replace(/ /g, '+');
- const googleFontUrl = `@import url('https://fonts.googleapis.com/css2?family=${fontFamily}:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');`;
+ if (quoteFont || quoteFontWeight || quoteFontStyle || quoteColor) {
+ let styleContent = '';
+
+ if (quoteFont) {
+ const fontFamily = quoteFont.replace(/ /g, '+');
+ styleContent += `@import url('https://fonts.googleapis.com/css2?family=${fontFamily}:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');\n`;
+ }
+
+ styleContent += '.quote, .quoteauthor {';
+ if (quoteFont) {
+ styleContent += `font-family: '${quoteFont}', 'Lexend Deca', 'Inter', sans-serif !important;`;
+ }
+ if (quoteFontWeight) {
+ styleContent += `font-weight: ${quoteFontWeight} !important;`;
+ }
+ if (quoteFontStyle) {
+ styleContent += `font-style: ${quoteFontStyle} !important;`;
+ }
+ if (quoteColor) {
+ styleContent += `color: ${quoteColor} !important;`;
+ }
+ styleContent += '}';
document.head.insertAdjacentHTML(
'beforeend',
- `
-
- `,
- );
- } else if (localStorage.getItem('quoteColor')) {
- const quoteColor = localStorage.getItem('quoteColor');
- document.head.insertAdjacentHTML(
- 'beforeend',
- `
-
- `,
+ ``,
);
}
@@ -272,15 +263,15 @@ export function loadSettings(hotreload) {
// easter egg
console.log(`
- █████████████████████████████████████████████████████████████
+ █████████████████████████████████████████████████████████████
+ ██ ██
+ ██ ███ ███ ██ ██ ███████ ██
+ ██ ████ ████ ██ ██ ██ ██
+ ██ ██ ████ ██ ██ ██ █████ ██
+ ██ ██ ██ ██ ██ ██ ██ ██
+ ██ ██ ██ ██████ ███████ ██
+ ██ ██
██ ██
- ██ ███ ███ ██ ██ ███████ ██
- ██ ████ ████ ██ ██ ██ ██
- ██ ██ ████ ██ ██ ██ █████ ██
- ██ ██ ██ ██ ██ ██ ██ ██
- ██ ██ ██ ██████ ███████ ██
- ██ ██
- ██ ██
██ Copyright 2018-${new Date().getFullYear()} The Mue Authors ██
██ GitHub: https://github.com/mue/mue ██
██ ██