diff --git a/apps/client/src/menus/custom-items/NoteColorPickerMenuItem.css b/apps/client/src/menus/custom-items/NoteColorPickerMenuItem.css index 35029699f..d062ea577 100644 --- a/apps/client/src/menus/custom-items/NoteColorPickerMenuItem.css +++ b/apps/client/src/menus/custom-items/NoteColorPickerMenuItem.css @@ -4,18 +4,22 @@ justify-content: space-between; } -.color-picker-menu-item .color-cell { +.color-picker-menu-item .color-cell { width: 14px; height: 14px; border-radius: 4px; - background: var(--color); + background-color: var(--color); } -.color-picker-menu-item .color-cell.disabled-color-cell { +.color-picker-menu-item .color-cell:not(.selected):hover { + transform: scale(1.2); +} + +.color-picker-menu-item .color-cell.disabled-color-cell { cursor: not-allowed; } -.color-picker-menu-item .color-cell.selected { +.color-picker-menu-item .color-cell.selected { outline: 2px solid var(--color); outline-offset: 2px; } @@ -28,7 +32,7 @@ left: 0; right: 0; bottom: 0; - font-size: 14px; + font-size: 18px; justify-content: center; align-items: center; font-family: boxicons; @@ -50,9 +54,16 @@ position: relative; display: flex; 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 { content: "\ed35"; color: var(--foreground); diff --git a/apps/client/src/menus/custom-items/NoteColorPickerMenuItem.tsx b/apps/client/src/menus/custom-items/NoteColorPickerMenuItem.tsx index 3db626013..96f7eba54 100644 --- a/apps/client/src/menus/custom-items/NoteColorPickerMenuItem.tsx +++ b/apps/client/src/menus/custom-items/NoteColorPickerMenuItem.tsx @@ -1,5 +1,5 @@ import "./NoteColorPickerMenuItem.css"; -import { useEffect, useRef, useState} from "preact/hooks"; +import { useCallback, useEffect, useRef, useState} from "preact/hooks"; import {ComponentChildren} from "preact"; import attributes from "../../services/attributes"; import Color, { ColorInstance } from "color"; @@ -22,12 +22,13 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr const [note, setNote] = useState(null); const [currentColor, setCurrentColor] = useState(null); + const [isCustomColor, setIsCustomColor] = useState(false); useEffect(() => { const retrieveNote = async (noteId: string) => { - const result = await froca.getNote(noteId, true); - if (result) { - setNote(result); + const noteInstance = await froca.getNote(noteId, true); + if (noteInstance) { + setNote(noteInstance); } } @@ -39,10 +40,27 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr }, []); 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]); - const onColorCellClicked = (color: string | null) => { + useEffect(() => { + setIsCustomColor(COLORS.indexOf(currentColor) === -1); + }, [currentColor]) + + const onColorCellClicked = useCallback((color: string | null) => { if (note) { if (color !== null) { attributes.setLabel(note.noteId, "color", color); @@ -52,7 +70,7 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr setCurrentColor(color); } - } + }, [note, currentColor]); return
{e.stopPropagation()}}> @@ -65,7 +83,9 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr onSelect={() => onColorCellClicked(color)} /> ))} - +
} @@ -87,28 +107,50 @@ function ColorCell(props: ColorCellProps) { } function CustomColorCell(props: ColorCellProps) { + const [pickedColor, setPickedColor] = useState(null); const colorInput = useRef(null); - let colorInputDebouncer: Debouncer; + const colorInputDebouncer = useRef | null>(null); + const callbackRef = useRef(props.onSelect); useEffect(() => { - colorInputDebouncer = new Debouncer(500, (color) => { - props.onSelect?.(color); + colorInputDebouncer.current = new Debouncer(500, (color) => { + callbackRef.current?.(color); + setPickedColor(color); }); 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
- {colorInput.current?.click()}}> + {colorInputDebouncer.updateValue(colorInput.current?.value ?? null)}} + value={pickedColor ?? props.color ?? "#40bfbf"} + onChange={() => {colorInputDebouncer.current?.updateValue(colorInput.current?.value ?? null)}} style="width: 0; height: 0; opacity: 0" />
diff --git a/apps/client/src/menus/custom-items/custom-culor.png b/apps/client/src/menus/custom-items/custom-culor.png new file mode 100644 index 000000000..4275c56d2 Binary files /dev/null and b/apps/client/src/menus/custom-items/custom-culor.png differ