client/note color picker: refactor

This commit is contained in:
Adorian Doran 2025-11-20 19:11:51 +02:00
parent b0476c7017
commit e4c928ae87

View File

@ -8,17 +8,17 @@ import Debouncer from "../../utils/debouncer";
import FNote from "../../entities/fnote"; import FNote from "../../entities/fnote";
import froca from "../../services/froca"; import froca from "../../services/froca";
const COLORS = [ const COLOR_PALETTE = [
"#e64d4d", "#e6994d", "#e5e64d", "#99e64d", "#4de64d", "#4de699", "#e64d4d", "#e6994d", "#e5e64d", "#99e64d", "#4de64d", "#4de699",
"#4de5e6", "#4d99e6", "#4d4de6", "#994de6", "#e64db3" "#4de5e6", "#4d99e6", "#4d4de6", "#994de6", "#e64db3"
]; ];
export interface NoteColorPickerMenuItemProps { export interface NoteColorPickerProps {
/** The target Note instance or its ID string. */ /** The target Note instance or its ID string. */
note: FNote | string | null; note: FNote | string | null;
} }
export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemProps) { export default function NoteColorPicker(props: NoteColorPickerProps) {
if (!props.note) return null; if (!props.note) return null;
const [note, setNote] = useState<FNote | null>(null); const [note, setNote] = useState<FNote | null>(null);
@ -43,14 +43,7 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
useEffect(() => { useEffect(() => {
const colorLabel = note?.getLabel("color")?.value ?? null; const colorLabel = note?.getLabel("color")?.value ?? null;
if (colorLabel) { if (colorLabel) {
let color: ColorInstance | null = null; let color = tryParseColor(colorLabel);
try {
color = new Color(colorLabel);
} catch(ex) {
console.error(ex);
}
if (color) { if (color) {
setCurrentColor(color.hex().toLowerCase()); setCurrentColor(color.hex().toLowerCase());
} }
@ -58,7 +51,7 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
}, [note]); }, [note]);
useEffect(() => { useEffect(() => {
setIsCustomColor(currentColor !== null && COLORS.indexOf(currentColor) === -1); setIsCustomColor(currentColor !== null && COLOR_PALETTE.indexOf(currentColor) === -1);
}, [currentColor]) }, [currentColor])
const onColorCellClicked = useCallback((color: string | null) => { const onColorCellClicked = useCallback((color: string | null) => {
@ -84,7 +77,7 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
onSelect={onColorCellClicked} /> onSelect={onColorCellClicked} />
{COLORS.map((color) => ( {COLOR_PALETTE.map((color) => (
<ColorCell key={color} <ColorCell key={color}
tooltip={t("note-color.set-color")} tooltip={t("note-color.set-color")}
color={color} color={color}
@ -155,7 +148,7 @@ function CustomColorCell(props: ColorCellProps) {
colorInput.current?.click(); colorInput.current?.click();
}, [pickedColor]); }, [pickedColor]);
return <div style={`--foreground: ${ensureContrast(props.color)};`}> return <div style={`--foreground: ${getForegroundColor(props.color)};`}>
<ColorCell {...props} <ColorCell {...props}
color={pickedColor} color={pickedColor}
className={`custom-color-cell ${(pickedColor === null) ? "custom-color-cell-empty" : ""}`} className={`custom-color-cell ${(pickedColor === null) ? "custom-color-cell-empty" : ""}`}
@ -170,17 +163,24 @@ function CustomColorCell(props: ColorCellProps) {
</div> </div>
} }
function ensureContrast(color: string | null) { function getForegroundColor(backgroundColor: string | null) {
if (color === null) return "inherit"; if (backgroundColor === null) return "inherit";
const colorHsl = Color(color).hsl(); const colorHsl = tryParseColor(backgroundColor)?.hsl();
let l = colorHsl.lightness(); if (colorHsl) {
let l = colorHsl.lightness();
if (l >= 40) { return colorHsl.saturationl(0).lightness(l >= 50 ? 0 : 100).hex();
l = 0;
} else { } else {
l = 100 return "inherit";
}
}
function tryParseColor(colorStr: string): ColorInstance | null {
try {
return new Color(colorStr);
} catch(ex) {
console.error(ex);
} }
return colorHsl.saturationl(0).lightness(l).hex(); return null;
} }