First steps toward tag selection

This commit is contained in:
Henrik Giesel 2021-06-29 16:50:54 +02:00
parent d3191d7ecb
commit 5c2911c053
3 changed files with 54 additions and 13 deletions

View File

@ -23,6 +23,20 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
setTimeout(() => (flashing = false), 300);
}
let showDelete = true;
function hideDeleteOnCtrlShfit(event: MouseEvent) {
showDelete = !event.ctrlKey && !event.shiftKey;
}
function showDeleteOnLeave() {
showDelete = true;
}
function toggleDelete() {
// TODO
}
const nightMode = getContext<boolean>(nightModeKey);
</script>
@ -32,11 +46,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
class:btn-day={!nightMode}
class:btn-night={nightMode}
tabindex="-1"
on:mousemove={hideDeleteOnCtrlShfit}
on:mouseleave={showDeleteOnLeave}
on:keydown={toggleDelete}
on:keyup={toggleDelete}
on:click
>
<span>{name}</span>
<Badge class="delete-icon rounded ms-1 mt-1" on:click={deleteTag}
>{@html deleteIcon}</Badge
<Badge
class={`delete-icon rounded ms-1 mt-1${showDelete ? "" : " opacity-0"}`}
on:click={deleteTag}>{@html deleteIcon}</Badge
>
</button>

0
ts/lib/keys.ts Normal file
View File

View File

@ -12,6 +12,14 @@ const platformModifiers = isApplePlatform()
? ["Meta", "Alt", "Shift", "Control"]
: ["Control", "Alt", "Shift", "OS"];
export function isControl(key: string): boolean {
return key === platformModifiers[0];
}
export function isShift(key: string): boolean {
return key === platformModifiers[2];
}
function modifiersToPlatformString(modifiers: string[]): string {
const displayModifiers = isApplePlatform()
? ["^", "⌥", "⇧", "⌘"]
@ -84,6 +92,23 @@ function checkKey(event: KeyboardEvent, key: number): boolean {
const allModifiers: Modifier[] = ["Control", "Alt", "Shift", "Meta"];
const checkModifiers =
(required: Modifier[], optional: Modifier[] = []) =>
(event: KeyboardEvent): boolean => {
return allModifiers.reduce(
(
matches: boolean,
currentModifier: Modifier,
currentIndex: number
): boolean =>
matches &&
(optional.includes(currentModifier as Modifier) ||
event.getModifierState(platformModifiers[currentIndex]) ===
required.includes(currentModifier)),
true
);
};
function partition<T>(predicate: (t: T) => boolean, items: T[]): [T[], T[]] {
const trueItems: T[] = [];
const falseItems: T[] = [];
@ -100,28 +125,25 @@ function removeTrailing(modifier: string): string {
return modifier.substring(0, modifier.length - 1);
}
function checkModifiers(event: KeyboardEvent, modifiers: string[]): boolean {
// function checkModifiers(event: KeyboardEvent, modifiers: string[]): boolean {
function separateRequiredOptionalModifiers(
modifiers: string[]
): [Modifier[], Modifier[]] {
const [requiredModifiers, otherModifiers] = partition(
isRequiredModifier,
modifiers
);
const optionalModifiers = otherModifiers.map(removeTrailing);
return allModifiers.reduce(
(matches: boolean, currentModifier: string, currentIndex: number): boolean =>
matches &&
(optionalModifiers.includes(currentModifier as Modifier) ||
event.getModifierState(platformModifiers[currentIndex]) ===
requiredModifiers.includes(currentModifier)),
true
);
return [requiredModifiers as Modifier[], optionalModifiers as Modifier[]];
}
const check =
(keyCode: number, modifiers: string[]) =>
(event: KeyboardEvent): boolean => {
return checkKey(event, keyCode) && checkModifiers(event, modifiers);
const [required, optional] = separateRequiredOptionalModifiers(modifiers);
return checkKey(event, keyCode) && checkModifiers(required, optional)(event);
};
function keyToCode(key: string): number {