mirror of
https://github.com/zadam/trilium.git
synced 2025-11-21 16:14:23 +01:00
client/note color picker menu item: improve
Some checks are pending
Checks / main (push) Waiting to run
Some checks are pending
Checks / main (push) Waiting to run
This commit is contained in:
parent
c25859cee9
commit
828a786414
@ -8,7 +8,11 @@
|
|||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: var(--color);
|
background-color: var(--color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-picker-menu-item .color-cell:not(.selected):hover {
|
||||||
|
transform: scale(1.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-picker-menu-item .color-cell.disabled-color-cell {
|
.color-picker-menu-item .color-cell.disabled-color-cell {
|
||||||
@ -28,7 +32,7 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
font-size: 14px;
|
font-size: 18px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-family: boxicons;
|
font-family: boxicons;
|
||||||
@ -50,9 +54,16 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: var(--color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.custom-color-cell.custom-color-cell-empty {
|
||||||
|
background-image: url(./custom-culor.png);
|
||||||
|
background-size: cover;
|
||||||
|
--foreground: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.custom-color-cell::before {
|
.custom-color-cell::before {
|
||||||
content: "\ed35";
|
content: "\ed35";
|
||||||
color: var(--foreground);
|
color: var(--foreground);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import "./NoteColorPickerMenuItem.css";
|
import "./NoteColorPickerMenuItem.css";
|
||||||
import { useEffect, useRef, useState} from "preact/hooks";
|
import { useCallback, useEffect, useRef, useState} from "preact/hooks";
|
||||||
import {ComponentChildren} from "preact";
|
import {ComponentChildren} from "preact";
|
||||||
import attributes from "../../services/attributes";
|
import attributes from "../../services/attributes";
|
||||||
import Color, { ColorInstance } from "color";
|
import Color, { ColorInstance } from "color";
|
||||||
@ -22,12 +22,13 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
|
|||||||
|
|
||||||
const [note, setNote] = useState<FNote | null>(null);
|
const [note, setNote] = useState<FNote | null>(null);
|
||||||
const [currentColor, setCurrentColor] = useState<string | null>(null);
|
const [currentColor, setCurrentColor] = useState<string | null>(null);
|
||||||
|
const [isCustomColor, setIsCustomColor] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const retrieveNote = async (noteId: string) => {
|
const retrieveNote = async (noteId: string) => {
|
||||||
const result = await froca.getNote(noteId, true);
|
const noteInstance = await froca.getNote(noteId, true);
|
||||||
if (result) {
|
if (noteInstance) {
|
||||||
setNote(result);
|
setNote(noteInstance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,10 +40,27 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentColor(note?.getLabel("color")?.value ?? null);
|
const colorLabel = note?.getLabel("color")?.value ?? null;
|
||||||
|
if (colorLabel) {
|
||||||
|
let color: ColorInstance | null = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
color = new Color(colorLabel);
|
||||||
|
} catch(ex) {
|
||||||
|
console.error(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color) {
|
||||||
|
setCurrentColor(color.hex().toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
}, [note]);
|
}, [note]);
|
||||||
|
|
||||||
const onColorCellClicked = (color: string | null) => {
|
useEffect(() => {
|
||||||
|
setIsCustomColor(COLORS.indexOf(currentColor) === -1);
|
||||||
|
}, [currentColor])
|
||||||
|
|
||||||
|
const onColorCellClicked = useCallback((color: string | null) => {
|
||||||
if (note) {
|
if (note) {
|
||||||
if (color !== null) {
|
if (color !== null) {
|
||||||
attributes.setLabel(note.noteId, "color", color);
|
attributes.setLabel(note.noteId, "color", color);
|
||||||
@ -52,7 +70,7 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
|
|||||||
|
|
||||||
setCurrentColor(color);
|
setCurrentColor(color);
|
||||||
}
|
}
|
||||||
}
|
}, [note, currentColor]);
|
||||||
|
|
||||||
return <div className="color-picker-menu-item"
|
return <div className="color-picker-menu-item"
|
||||||
onClick={(e) => {e.stopPropagation()}}>
|
onClick={(e) => {e.stopPropagation()}}>
|
||||||
@ -65,7 +83,9 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
|
|||||||
onSelect={() => onColorCellClicked(color)} />
|
onSelect={() => onColorCellClicked(color)} />
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<CustomColorCell color={currentColor} isSelected={false} onSelect={onColorCellClicked} />
|
<CustomColorCell color={currentColor}
|
||||||
|
isSelected={isCustomColor}
|
||||||
|
onSelect={onColorCellClicked} />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,28 +107,50 @@ function ColorCell(props: ColorCellProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function CustomColorCell(props: ColorCellProps) {
|
function CustomColorCell(props: ColorCellProps) {
|
||||||
|
const [pickedColor, setPickedColor] = useState<string | null>(null);
|
||||||
const colorInput = useRef<HTMLInputElement>(null);
|
const colorInput = useRef<HTMLInputElement>(null);
|
||||||
let colorInputDebouncer: Debouncer<string | null>;
|
const colorInputDebouncer = useRef<Debouncer<string | null> | null>(null);
|
||||||
|
const callbackRef = useRef(props.onSelect);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
colorInputDebouncer = new Debouncer(500, (color) => {
|
colorInputDebouncer.current = new Debouncer(500, (color) => {
|
||||||
props.onSelect?.(color);
|
callbackRef.current?.(color);
|
||||||
|
setPickedColor(color);
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
colorInputDebouncer.destroy();
|
colorInputDebouncer.current?.destroy();
|
||||||
}
|
}
|
||||||
});
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.isSelected && pickedColor === null) {
|
||||||
|
setPickedColor(props.color);
|
||||||
|
}
|
||||||
|
}, [props.isSelected])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
callbackRef.current = props.onSelect;
|
||||||
|
}, [props.onSelect]);
|
||||||
|
|
||||||
|
const onSelect = useCallback(() => {
|
||||||
|
if (pickedColor !== null) {
|
||||||
|
callbackRef.current?.(pickedColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
colorInput.current?.click();
|
||||||
|
}, [pickedColor]);
|
||||||
|
|
||||||
return <div style={`--foreground: ${ensureContrast(props.color)};`}>
|
return <div style={`--foreground: ${ensureContrast(props.color)};`}>
|
||||||
<ColorCell {...props}
|
<ColorCell {...props}
|
||||||
className="custom-color-cell"
|
color={pickedColor}
|
||||||
onSelect={() => {colorInput.current?.click()}}>
|
className={`custom-color-cell ${(pickedColor === null) ? "custom-color-cell-empty" : ""}`}
|
||||||
|
onSelect={onSelect}>
|
||||||
|
|
||||||
<input ref={colorInput}
|
<input ref={colorInput}
|
||||||
type="color"
|
type="color"
|
||||||
value={props.color ?? ""}
|
value={pickedColor ?? props.color ?? "#40bfbf"}
|
||||||
onChange={() => {colorInputDebouncer.updateValue(colorInput.current?.value ?? null)}}
|
onChange={() => {colorInputDebouncer.current?.updateValue(colorInput.current?.value ?? null)}}
|
||||||
style="width: 0; height: 0; opacity: 0" />
|
style="width: 0; height: 0; opacity: 0" />
|
||||||
</ColorCell>
|
</ColorCell>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
BIN
apps/client/src/menus/custom-items/custom-culor.png
Normal file
BIN
apps/client/src/menus/custom-items/custom-culor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
Loading…
x
Reference in New Issue
Block a user