Skip to content

Commit 828a786

Browse files
committed
client/note color picker menu item: improve
1 parent c25859c commit 828a786

File tree

3 files changed

+77
-24
lines changed

3 files changed

+77
-24
lines changed

apps/client/src/menus/custom-items/NoteColorPickerMenuItem.css

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,22 @@
44
justify-content: space-between;
55
}
66

7-
.color-picker-menu-item .color-cell {
7+
.color-picker-menu-item .color-cell {
88
width: 14px;
99
height: 14px;
1010
border-radius: 4px;
11-
background: var(--color);
11+
background-color: var(--color);
1212
}
1313

14-
.color-picker-menu-item .color-cell.disabled-color-cell {
14+
.color-picker-menu-item .color-cell:not(.selected):hover {
15+
transform: scale(1.2);
16+
}
17+
18+
.color-picker-menu-item .color-cell.disabled-color-cell {
1519
cursor: not-allowed;
1620
}
1721

18-
.color-picker-menu-item .color-cell.selected {
22+
.color-picker-menu-item .color-cell.selected {
1923
outline: 2px solid var(--color);
2024
outline-offset: 2px;
2125
}
@@ -28,7 +32,7 @@
2832
left: 0;
2933
right: 0;
3034
bottom: 0;
31-
font-size: 14px;
35+
font-size: 18px;
3236
justify-content: center;
3337
align-items: center;
3438
font-family: boxicons;
@@ -50,9 +54,16 @@
5054
position: relative;
5155
display: flex;
5256
justify-content: center;
53-
background: var(--color);
57+
5458
}
5559

60+
.custom-color-cell.custom-color-cell-empty {
61+
background-image: url(./custom-culor.png);
62+
background-size: cover;
63+
--foreground: transparent;
64+
}
65+
66+
5667
.custom-color-cell::before {
5768
content: "\ed35";
5869
color: var(--foreground);

apps/client/src/menus/custom-items/NoteColorPickerMenuItem.tsx

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import "./NoteColorPickerMenuItem.css";
2-
import { useEffect, useRef, useState} from "preact/hooks";
2+
import { useCallback, useEffect, useRef, useState} from "preact/hooks";
33
import {ComponentChildren} from "preact";
44
import attributes from "../../services/attributes";
55
import Color, { ColorInstance } from "color";
@@ -22,12 +22,13 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
2222

2323
const [note, setNote] = useState<FNote | null>(null);
2424
const [currentColor, setCurrentColor] = useState<string | null>(null);
25+
const [isCustomColor, setIsCustomColor] = useState<boolean>(false);
2526

2627
useEffect(() => {
2728
const retrieveNote = async (noteId: string) => {
28-
const result = await froca.getNote(noteId, true);
29-
if (result) {
30-
setNote(result);
29+
const noteInstance = await froca.getNote(noteId, true);
30+
if (noteInstance) {
31+
setNote(noteInstance);
3132
}
3233
}
3334

@@ -39,10 +40,27 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
3940
}, []);
4041

4142
useEffect(() => {
42-
setCurrentColor(note?.getLabel("color")?.value ?? null);
43+
const colorLabel = note?.getLabel("color")?.value ?? null;
44+
if (colorLabel) {
45+
let color: ColorInstance | null = null;
46+
47+
try {
48+
color = new Color(colorLabel);
49+
} catch(ex) {
50+
console.error(ex);
51+
}
52+
53+
if (color) {
54+
setCurrentColor(color.hex().toLowerCase());
55+
}
56+
}
4357
}, [note]);
4458

45-
const onColorCellClicked = (color: string | null) => {
59+
useEffect(() => {
60+
setIsCustomColor(COLORS.indexOf(currentColor) === -1);
61+
}, [currentColor])
62+
63+
const onColorCellClicked = useCallback((color: string | null) => {
4664
if (note) {
4765
if (color !== null) {
4866
attributes.setLabel(note.noteId, "color", color);
@@ -52,7 +70,7 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
5270

5371
setCurrentColor(color);
5472
}
55-
}
73+
}, [note, currentColor]);
5674

5775
return <div className="color-picker-menu-item"
5876
onClick={(e) => {e.stopPropagation()}}>
@@ -65,7 +83,9 @@ export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemPr
6583
onSelect={() => onColorCellClicked(color)} />
6684
))}
6785

68-
<CustomColorCell color={currentColor} isSelected={false} onSelect={onColorCellClicked} />
86+
<CustomColorCell color={currentColor}
87+
isSelected={isCustomColor}
88+
onSelect={onColorCellClicked} />
6989
</div>
7090
}
7191

@@ -87,28 +107,50 @@ function ColorCell(props: ColorCellProps) {
87107
}
88108

89109
function CustomColorCell(props: ColorCellProps) {
110+
const [pickedColor, setPickedColor] = useState<string | null>(null);
90111
const colorInput = useRef<HTMLInputElement>(null);
91-
let colorInputDebouncer: Debouncer<string | null>;
112+
const colorInputDebouncer = useRef<Debouncer<string | null> | null>(null);
113+
const callbackRef = useRef(props.onSelect);
92114

93115
useEffect(() => {
94-
colorInputDebouncer = new Debouncer(500, (color) => {
95-
props.onSelect?.(color);
116+
colorInputDebouncer.current = new Debouncer(500, (color) => {
117+
callbackRef.current?.(color);
118+
setPickedColor(color);
96119
});
97120

98121
return () => {
99-
colorInputDebouncer.destroy();
122+
colorInputDebouncer.current?.destroy();
123+
}
124+
}, []);
125+
126+
useEffect(() => {
127+
if (props.isSelected && pickedColor === null) {
128+
setPickedColor(props.color);
129+
}
130+
}, [props.isSelected])
131+
132+
useEffect(() => {
133+
callbackRef.current = props.onSelect;
134+
}, [props.onSelect]);
135+
136+
const onSelect = useCallback(() => {
137+
if (pickedColor !== null) {
138+
callbackRef.current?.(pickedColor);
100139
}
101-
});
140+
141+
colorInput.current?.click();
142+
}, [pickedColor]);
102143

103144
return <div style={`--foreground: ${ensureContrast(props.color)};`}>
104-
<ColorCell {...props}
105-
className="custom-color-cell"
106-
onSelect={() => {colorInput.current?.click()}}>
145+
<ColorCell {...props}
146+
color={pickedColor}
147+
className={`custom-color-cell ${(pickedColor === null) ? "custom-color-cell-empty" : ""}`}
148+
onSelect={onSelect}>
107149

108150
<input ref={colorInput}
109151
type="color"
110-
value={props.color ?? ""}
111-
onChange={() => {colorInputDebouncer.updateValue(colorInput.current?.value ?? null)}}
152+
value={pickedColor ?? props.color ?? "#40bfbf"}
153+
onChange={() => {colorInputDebouncer.current?.updateValue(colorInput.current?.value ?? null)}}
112154
style="width: 0; height: 0; opacity: 0" />
113155
</ColorCell>
114156
</div>
1.23 KB
Loading

0 commit comments

Comments
 (0)